2010-04-15 96 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