Assigning size_t to off_t produces sign-conversion error

I’m using gcc of the following version:

$ gcc --version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0

Consider the following simple code fragment compiled with -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 live example

According to N2596/6.5.3.4 The sizeof and _Alignof operators:

The value of the result of both operators is implementation-defined,
and its type (an unsigned integer type) is size_t, defined in
<stddef.h> (and other headers).

So it appeared to me that the result of off_t off_1 = sz; should be the same as off_t off_2 = sizeof(long);

Why does off_t off_1 = sz; produces this error?

  • 1

    OT: You can probably see the same with simpler code without use of sizeof. Try size_t sz = 8; off_t off_1 = sz; off_t off_2 = (size_t)8;

    – 

This line:

off_t off_1 = sz;

Is producing an error because sz on your system is an unsigned 64 bit value (long unsigned int), and off_1 is a signed 64 bit value (long int).
In the general case there are values of sz that cannot be fitted into off_1.

However in this line:

off_t off_2 = sizeof(long);

sizeof(long) is a compile time constant (8 on your system), and the compiler can verify that it can be safely assigned into off_t off_2.

Leave a Comment