2014-01-16 19 views
4

当我编译下面以这种方式与G ++ 4.8.1(64位)代码:为什么G ++ 4.8.1问题转换警告

$ g++ -Wconversion -o main main.cpp 

我得到这样的结果:

main.cpp: In function ‘int main()’: 
main.cpp:12:20: warning: conversion to ‘int’ from ‘long unsigned int’ may alter its value [-Wconversion] 
    int i = sizeof(x)/sizeof(x[0]); 
        ^

我的期望是编译器应该能够在编译时评估表达式。如果你用普通的c做类似的程序,gcc就像魅力一样。

这应该被认为是g ++中的一个bug(例如clang ++没有这个问题)?

如果你改变了有问题的行是这样的:

char c = 0x10000000/0x1000000; 

那么编译器不抱怨。这表明一些不断的评估是在警告产生之前完成的。

main.cpp中:

#include <iostream> 

struct foo { 
    int a; 
    int b; 
}; 

foo x[50]; 

int main() 
{ 
    int i = sizeof(x)/sizeof(x[0]); 
    std::cout << i << std::endl; 

    return 0; 
} 
+0

那是不是没有优化?试试'-O2',它应该在编译时评估它。 – Rup

+0

我的确也收到了4.8的警告,但是我不会在4.9版本(大约一周前的GCC源代码)中出现,所以我认为GCC开发人员认为这是一个bug并且已经修复了它。 – hvd

回答

7
int i = sizeof(x)/sizeof(x[0]); 
//int <-- std::size_t <-- std::size_t/std::size_t 

类型表达sizeof(x)/sizeof(x[0])的是std::size_t其在机器上是unsigned long int。因此,如果源的大小大于目标,则从此类型到int的转换是数据丢失。

虽然,我同意你的情况,就是实际的数据丢失,如果编译器实际上计算的价值,但我想它的实际计算之前应用-Wconversion

+0

虽然它看起来像是警告。它应该仍然在这个时候除以两个'unsigned long int',不是吗?或者,在分割(!)之前是否将预期的“int”赋值赋值给它? – Rup

+1

除法是问题,因为它是转换为“int”的操作的结果。该部门本身是安全的。 –

+1

任何人都可以提供一个标准报价,说在编译时评估表达式可以忽略标准中的其他规则吗?我只能找到一个说明,即浮点运算可以给出不同的结果,因为没有指定浮点精度。为什么这个问题的转换不符合标准转换规则? –

0

sizeof()返回你std::size_t不是int!因此,将其投射或声明istd::size_t

std::size_t i = sizeof(x)/sizeof(x[0]); 
+1

或使用'auto'。 –

+0

@BЈовић它的C + + 11权利? ..感谢您的信息! –

+0

是的,那是来自C++ 11 –