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

Som*_*ame 2 c sizeof

我正在使用以下版本的 gcc:

$ gcc --version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Run Code Online (Sandbox Code Playgroud)

考虑使用以下编译的简单代码片段-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;
}
Run Code Online (Sandbox Code Playgroud)

Godbolt 实例

根据N2596/6.5.3.4sizeof_Alignof运算符:

两个运算符的结果值都是实现定义的,其类型(无符号整数类型)是size_t,在(和其他标头)中定义 <stddef.h>

所以在我看来,结果off_t off_1 = sz;应该与 off_t 相同off_2 = sizeof(long);

为什么会off_t off_1 = sz;产生这个错误?

woh*_*tad 5

这行:

off_t off_1 = sz;
Run Code Online (Sandbox Code Playgroud)

产生错误是因为sz您的系统上有一个无符号64 位值 ( long unsigned int),并且off_1是一个有符号64 位值 ( long int)。在一般情况下,有些值sz无法拟合到 中off_1

然而在这一行中:

off_t off_2 = sizeof(long);
Run Code Online (Sandbox Code Playgroud)

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

  • 关于“*在您的系统上*”,C 类型 `size_t` 始终是无符号的(尽管并不总是 64 位),而 POSIX 类型 `off_t` 始终是有符号的(尽管并不总是 64 位)。 (2认同)