2010-04-15 3 views
1

이 코드는 xlC 8.0 (AIX 5.3)에서 컴파일 될 때 잘못된 결과를 생성합니다. 12345을 인쇄해야하지만 대신 804399880을 인쇄하십시오. result 앞에있는 const을 제거하면 코드가 올바르게 작동합니다.Consts 초기화 문제

버그는 어디에 있습니까?

#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 

편집 : 위의 printf와 형식 문자열을 변경 "% ld 개 \ 없음"도움이되지 않습니다. 편집 2 : 사용 된 AIX 버전은 6.1이 아닌 5.3입니다. printf와의 % u 개의 지정이 부호없는 정수를 나타냅니다,하지만 당신은 정수를 전달하는 미세한

+0

아마도 컴파일러 문제가 ... VS2008 및 gcc (mingw)와 함께 작동합니다. – INS

+0

AIX 5.3에서 XL C/C++ 8.0을 사용하여 저에게 적합합니다. 흥미 롭 군. –

+0

@Fred 어떤 xlc 버전을 사용하고 있습니까? (xlC -qversion) 08.00.0000.0000을 사용하고 있습니다. –

답변

3

xlC가 10.0 작품은 컴파일러의 버그가 아마 관련이없는

+0

또한 VC++ 2005에서 작동하도록 확인했습니다. – KevenK

+0

예, xlC v10.1에서도 작동합니다. –

0

에게, 그러나 조심해야 할 것 같다.

0

g ++은이 문제를 잘 처리하며 경고는 언급하지 않습니다. 그것은 printf에 대해 불평합니다. long int에는 % lu를 사용해야합니다. 또는 % ld를 사용하거나 캐스팅 (unsigned long int)하는 것이 더 좋습니다.

+6

실제로'% ld'입니다. –

+0

아니면 iostream을 사용하고 전체적인 문제를 피하십시오. –

+0

예, % ld은 좋지만 g ++은 % lu와 (과) 잘 맞습니다. 숫자가 잘못 해석 되더라도 상관 없습니다. 올바른 길이 일뿐입니다. – clahey

2

이것은 C++ 태그가 붙어 있으므로 printf 대신 cout을 사용하면 어떻게됩니까?

printf에 부호없는 int를 출력 한 다음 서명 된 long int를 보내 인쇄하는 것이 문제인 것처럼 보입니다. 대부분 메모리 레이아웃이 다르기 때문에 printf는 실제로하고 싶은 것을 이해하지 못합니다.

1

const가 중요한 이유는 추측이지만, 합리적인 가정을 할 수 있습니다.

블록 범위가있는 변수 (예 : result)를 레지스터에 할당하거나 스택에 배치 할 수 있습니다. 레지스터 사용 여부에 영향을 미치는 많은 요소가 있습니다. 이 경우에는 const이 중요 할 수 있습니다. 결국, 가장 잘 작동한다고 생각하는 것을 사용할 수있는 컴파일러가 될 것입니다.

마찬가지로 함수에 대한 인수는 레지스터 나 스택에 전달 될 수 있습니다. 함수는 종종 별도로 컴파일되므로 인터페이스 (예 : 선언)는 어느 인수가 어디로 갈지를 결정합니다. printf (...)는 다른 타입의 인자로 호출 될 수 있기 때문에 특별한 경우이다. 결과적으로, 어떤 데이터가 어디에서 끝나는 지 끝내고 printf (...)에게 무엇을 기대해야하는지 알려줘야합니다.

이제 변수를 함수에 전달할 때 컴파일러는 일반적으로이를 복사해야합니다. 레지스터에서 스택으로, 하나의 레지스터에서 다른 레지스터로, 많은 변형이 가능합니다. 앞에서 설명한대로 소스 위치는 const의 유무에 따라 다를 수 있습니다.

잘못된 형식 지정자를 printf(...)으로 전달합니다. 즉, %ld 대신 %u이 전달됩니다. 이로 인해 printf (...)가 잘못된 위치에서 데이터를 가져올 수 있습니다. 스택 대신 레지스터 또는 다른 방법으로 처리 할 수 ​​있습니다. 이러한 행동은 놀라운 결과를 초래할 수 있습니다. printf(...)은 예를 들어 복사되지 않은 result을 가로 지르거나 임의의 이전 값을 일부 레지스터에서 발견 할 수 있습니다. const가 아닌 경우 올바른 값을 찾은 것 같습니다 (비록 잘못된 위치에서 발견했을지라도). 반면에 const의 경우 printf(...)은 그냥 가비지를 찾습니다.

+0

고마워요.하지만 코드는 32 비트이므로 "% u"와 "% ld"는 같은 크기입니다. –