将size_t分配给off_t会产生符号转换错误

Assigning size_t to off_t produces sign-conversion error

提问人:Some Name 提问时间:10/13/2023 更新时间:10/13/2023 访问量:100

问:

我正在使用以下版本的 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;
}

Godbolt 现场示例

根据 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;

c sizeof

评论

1赞 Support Ukraine 10/13/2023
OT:在不使用 .尝试sizeofsize_t sz = 8; off_t off_1 = sz; off_t off_2 = (size_t)8;

答:

5赞 wohlstad 10/13/2023 #1

这一行:

off_t off_1 = sz;

产生错误,因为系统上有一个符号的 64 位值 (),并且是有符号的 64 位值 ()。 在一般情况下,有些值不能拟合到 中。szlong unsigned intoff_1long intszoff_1

但是,在这一行中:

off_t off_2 = sizeof(long);

sizeof(long)是一个编译时常量(在您的系统上),编译器可以验证它是否可以安全地分配给 。8off_t off_2

评论

2赞 ikegami 10/13/2023
在“您的系统上”,C 类型始终是无符号的(尽管并不总是 64 位),而 POSIX 类型始终是有符号的(尽管并不总是 64 位)。size_toff_t
0赞 wohlstad 10/13/2023
@ikegami我认为理论上(尽管可能性很小)可能存在一个 32 位无符号的系统,但一个 64 位有符号的系统,在这样的系统上编译器不应该产生错误。这就是为什么我提到当前的系统是相关的。size_toff_t
1赞 Lundin 10/13/2023
而且似乎 gcc 实际上足够聪明,可以警告可疑的编译时常量 - 例如也发出警告。off_t off_2 = 1ul << (8*sizeof(long)-1);-Wsign-conversion
0赞 0___________ 10/13/2023
@Lundin更简单的非编译时 const 示例将给出一个错误 godbolt.org/z/Te3sPK5Wxsizeof