提问人:Some Name 提问时间:10/13/2023 更新时间:10/13/2023 访问量:100
将size_t分配给off_t会产生符号转换错误
Assigning size_t to off_t produces sign-conversion error
问:
我正在使用以下版本的 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 算子的大小
和_Alignof
:
两个运算符的结果值都是由实现定义的, 其类型(无符号整数类型)为 ,在 (和其他标头)中定义。
size_t
<stddef.h>
所以在我看来,结果应该和off_toff_t off_1 = sz;
off_2 = sizeof(long);
为什么会产生此错误?off_t off_1 = sz;
答:
5赞
wohlstad
10/13/2023
#1
这一行:
off_t off_1 = sz;
产生错误,因为系统上有一个无符号的 64 位值 (),并且是有符号的 64 位值 ()。
在一般情况下,有些值不能拟合到 中。sz
long unsigned int
off_1
long int
sz
off_1
但是,在这一行中:
off_t off_2 = sizeof(long);
sizeof(long)
是一个编译时常量(在您的系统上),编译器可以验证它是否可以安全地分配给 。8
off_t off_2
评论
2赞
ikegami
10/13/2023
在“您的系统上”,C 类型始终是无符号的(尽管并不总是 64 位),而 POSIX 类型始终是有符号的(尽管并不总是 64 位)。size_t
off_t
0赞
wohlstad
10/13/2023
@ikegami我认为理论上(尽管可能性很小)可能存在一个 32 位无符号的系统,但一个 64 位有符号的系统,在这样的系统上编译器不应该产生错误。这就是为什么我提到当前的系统是相关的。size_t
off_t
1赞
Lundin
10/13/2023
而且似乎 gcc 实际上足够聪明,可以警告可疑的编译时常量 - 例如也发出警告。off_t off_2 = 1ul << (8*sizeof(long)-1);
-Wsign-conversion
下一个:多级继承和空基优化中的内存布局
评论
sizeof
size_t sz = 8; off_t off_1 = sz; off_t off_2 = (size_t)8;