我正在使用以下版本的gcc:
$ gcc --version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
考虑以下使用
-Werror=sign-conversion
编译的简单代码片段:
#include <stddef.h>
#include <sys/types.h>
int main(void){
size_t sz = sizeof(long);
off_t off_1 = sz; //error: conversion to 'off_t' {aka 'long int'} from 'size_t' {aka 'long unsigned int'} may change the sign of the result
off_t off_2 = sizeof(long); //compiles fine
return 0;
}
根据 N2596/6.5.3.4
sizeof
和 _Alignof
运算符:
两个运算符的结果值都是实现定义的, 它的类型(无符号整数类型)是
,定义于size_t
(和其他标题)。<stddef.h>
所以在我看来,
off_t off_1 = sz;
的结果应该与off_t off_2 = sizeof(long);
相同
为什么
off_t off_1 = sz;
会产生这个错误?
这一行:
off_t off_1 = sz;
产生错误,因为
sz
是一个 unsigned 64 位值 (long unsigned int
),而 off_1
是一个 signed 64 位值 (long int
)。
一般情况下,有些 sz
的值无法拟合到 off_1
中。
但是在这一行中:
off_t off_2 = sizeof(long);
sizeof(long)
是一个编译时常量,编译器可以验证它是否可以安全地赋值给off_t off_2
。