2010-04-15 76 views
1

在xlC 8.0(在AIX 5.3上)編譯時,此代碼會產生錯誤的結果。 它應該打印12345,而是打印804399880。 刪除result前面的const使代碼正常工作。初始化控制檯問題

錯誤在哪裏?

#include <stdio.h> 
#include <stdlib.h> 
#include <string> 

long int foo(std::string input) 
{ 
     return strtol(input.c_str(), NULL, 0); 
} 

void bar() 
{ 
     const long int result = foo("12345"); 
     printf("%u\n", result); 
} 

int 
main() 
{ 
     bar(); 
     return 0; 
} 

編譯命令:

/usr/vacpp/bin/xlC example.cpp -g 

編輯:更改上面的格式化字符串 「%LD \ N」 沒有幫助。 編輯2:使用的AIX版本是5.3,而不是6.1。

+0

可能是一個編譯器問題...它適用於VS2008和gcc(mingw) – INS 2010-04-15 13:09:23

+0

適用於我在AIX 5.3上使用XL C/C++ 8.0。有趣。 – 2010-04-15 13:27:19

+0

@Fred你正在使用什麼版本的xlc? (xlC -qversion) 我使用的是08.00.0000.0000。 – 2010-04-17 13:42:24

回答

3

方xIC 10.0優良工程,似乎是一個編譯器缺陷

+0

確認也可以在VC++ 2005中工作 – KevenK 2010-04-15 13:06:37

+0

是的,它也適用於xlC v10.1中的我。 – 2010-04-15 13:22:14

0

可能不相關,但要注意:對於在printf%U符表示一個無符號整數,但你傳遞一個符號整數。

0

g ++處理這個很好,並沒有提到警告。它確實抱怨printf。你應該使用%lu作爲long int。或者甚至更好,使用%ld或者轉換爲(unsigned long int)。

+6

'%ld'實際上。 – 2010-04-15 13:08:52

+0

或者只是使用iostream並避免整個問題。 – 2010-04-15 13:29:47

+0

是的,%ld會更好,但g ++對%lu很好。它並不在乎數字被解釋爲錯誤,只是它的長度正確。 – clahey 2010-04-15 16:31:37

2

這是標籤爲C++,所以當你使用cout而不是printf時會發生什麼?

它看起來像問題是你告訴printf打印一個unsigned int,然後發送一個簽名的長整型實際打印。最有可能的內存佈局是不同的,並且printf不能理解你實際想要做什麼。

1

這將是一個猜測爲什麼常量很重要,但可以做出合理的假設。

塊範圍的變量(如result)可以分配給寄存器或放入堆棧。影響是否使用寄存器的因素很多。在這種情況下,const很有可能很重要。最終,編譯人員有權使用它認爲最好的方法。

類似地,函數的參數可以在寄存器或堆棧中傳遞。由於函數通常是單獨編譯的,它們的接口(即聲明)指示哪個參數在哪裏。 printf(...)是一個特例,因爲它可以用不同類型的參數來調用。因此,哪些數據會在哪裏變化,並且您需要告訴printf(...)會發生什麼。

現在,當一個變量傳遞給函數時,編譯器通常需要複製它。從寄存器到堆棧,一個寄存器到另一個寄存器等等,可能有很多變化。正如我所指出的,根據const的存在或不存在,來源位置可能會有所不同。

現在碰巧你將錯誤的格式說明符傳遞給printf(...),即%u而不是%ld。這可能會導致printf(...)在錯誤的地方查找數據 - 可能是在寄存器而不是堆棧中,或者反過來。這樣的行爲可能會導致相當令人驚訝的結果。 printf(...)可能會偶然發現您的未知錯誤result,或某些寄存器中的隨機舊值。看起來,在非常量情況下它恰好找到了正確的值(儘管它可能發現它在錯誤的地方),而在常量情況下printf(...)只是發現垃圾。

+0

謝謝,但代碼是32位的,所以「%u」和「%ld」的大小相同。 – 2010-04-17 15:43:50