即使使用unsigned long int也会出现溢出

Kri*_*fer 29 c

当我进行以下计算时:

unsigned long long int data_size = 60123456 * 128 * sizeof(double);
printf("data_size= %llu  \n", data_size);
Run Code Online (Sandbox Code Playgroud)

我出乎意料地得到溢出警告:

test.c:20:49: warning: overflow in expression; result is -894132224 with type 'int' [-Winteger-overflow]
    unsigned long long int data_size = 60123456 * 128 * sizeof(double);
                                                ^
1 warning generated.
Run Code Online (Sandbox Code Playgroud)

即使我正在使用,我也无法理解为什么会出现此错误unsigned long long int!有人可以解释原因吗?谢谢

Jea*_*bre 45

在将值赋给变量之前发生溢出.为避免使用长long后缀:

60123456LL * 128 * sizeof(double)
Run Code Online (Sandbox Code Playgroud)

(评论还建议ULL在这里没有必要,因为值在符号范围内,但这将是通用的方法)

  • 在这种情况下,@ glglgl`U`不需要,但是`U`对于通用情况更好.考虑`60123456LL*300000000000`.没有`U`,这又是有符号整数溢出,即使数学产品适合`unsigned long long`.最好用目标类型的宽度进行数学计算. (21认同)
  • @chux 同意,几乎我见过的所有编码指南都不喜欢无符号签名 -> 无符号转换。 (2认同)

glg*_*lgl 18

你转得太久了很长时间.60123456 * 128仍然是一个溢出的int表达式.

试试吧60123456LL * 128.(LL,因为结果值不能保证适合长期.)

  • `LL`对于更接近适合的计算是有用的,但目标类型是`unsigned long long`,而不是'long long`.ULL最适合用于"无符号长long"目标的常量的一般计算. (2认同)

chu*_*ica 12

unsigned long long int data_size = 60123456 * 128 * sizeof(double);  // trouble-some code
Run Code Online (Sandbox Code Playgroud)

目的地类型unsigned long long int data_size =与产品计算无关60123456 * 128 * sizeof(double).

最好确保使用至少目标类型的大小来完成数学运算以避免溢出.在OP的情况下,这意味着一个常数LLU.


有2个产品计算,每个都有自己的类型数学.

60123456是一个int或long取决于int范围.让我们假设它是一个int.

60123456 * 128是一个int * int.数学乘积7695802368超过32位有符号整数 范围,因此带有32位的带符号整数溢出或未定义行为(UB)int.

如果60123456 * 128没有溢出,说64位int,比下的乘法会* sizeof(double);等int * size_t导致size_t的产品类型.

产品计算应至少使用unsigned long long数学如下:

unsigned long long int data_size = 1LLU * 60123456 * 128 * sizeof(double);

// or
unsigned long long int data_size = 60123456LLU * 128 * sizeof(double);

// or 
unsigned long long int data_size = 60123456;
data_size *= 128 * sizeof(double);

// or avoiding naked magic numbers
#define A_HEIGHT 60123456
#define A_WIDTH 128
unsigned long long int data_size = 1LLU * A_HEIGHT * A_WIDTH * sizeof(double);
Run Code Online (Sandbox Code Playgroud)

sizeof (double)代码试图找到某些类似2D结构的大小的提示.我希望代码如下.注意结果类型sizeof是size_t,所以产品数学至少使用数学来完成size_t.

size_t data_size = sizeof(double) * 60123456 * 128;
printf("data_size= %zu\n", data_size);
Run Code Online (Sandbox Code Playgroud)

另请参阅为什么在C中将1,000,000,000写入1000*1000*1000? 我的答案理由是不使用1000*1000*1000的适用细节..