C question: off_t (and other signed integer types) minimum and maximum values

后端 未结 9 1004
耶瑟儿~
耶瑟儿~ 2020-12-06 05:58

I occasionally will come across an integer type (e.g. POSIX signed integer type off_t) where it would be helpful to have a macro for its minimum and maximum val

相关标签:
9条回答
  • 2020-12-06 06:30

    I believe I have finally solved this problem, but the solution is only available at configure-time, not compile-time or runtime, so it's still not idea. Here it is:

    HEADERS="#include <sys/types.h>"
    TYPE="off_t"
    i=8
    while : ; do
    printf "%s\nstruct { %s x : %d; };\n" "$HEADERS" "$TYPE" $i > test.c
    $CC $CFLAGS -o /dev/null -c test.c || break
    i=$(($i+1))
    done
    rm test.c
    echo $(($i-1))
    

    The idea comes from 6.7.2.1 paragraph 3:

    The expression that specifies the width of a bit-field shall be an integer constant expression with a nonnegative value that does not exceed the width of an object of the type that would be specified were the colon and expression omitted. If the value is zero, the declaration shall have no declarator.

    I would be quite pleased if this leads to any ideas for solving the problem at compile-time.

    0 讨论(0)
  • 2020-12-06 06:39

    Quick answers only:

    #define UINT_WHATEVER_T_MAX ( ~ (uint_whatever_t) 0 ) looks OK to me, the preference for -1 is that uint_whatever_t = -1; is more concise than uint_whatever_t = ~(uint_whatever_t)0;

    (CHAR_BIT * sizeof(t)) looks not strictly conforming to me. You're right about padding bits, so this value might be considerably more than the width of the type unless Posix says otherwise about off_t.

    In contrast, the fixed-width integer types in C99 must not have padding bits, so for intN_t you're on firmer ground using the size to deduce the width. They're also guaranteed two's complement.

    That would seem to imply that only those three listed signed number representations can be used. Is the implication correct

    Yes. 6.2.6.2/2 lists the three permissible meanings of the sign bit, and hence the three permissible signed number representations.

    is the sign bit guaranteed to always be one more significant than the most significant value bit

    It's indirectly required to be more significant than the value bits, by the fact (6.2.6.2/2 again) that "Each bit that is a value bit shall have the same value as the same bit in the object representation of the corresponding unsigned type". So the value bits must be a contiguous range starting at the least significant.

    However, you can't portably set just the sign bit. Read 6.2.6.2/3 and /4, about negative zeros, and note that even if the implementation uses a representation that has them in principle, it doesn't have to support them, and there's no guaranteed way of generating one. On a sign+magnitude implementation, the thing you want is a negative zero.

    [Edit: oh, I misread, you only need to generate that value after you've ruled out sign+magnitude, so you could still be OK.

    To be honest, it sounds a bit numpty to me if Posix has defined an integer type and not provided limits for it. Boo to them. I'd probably go with the old, "porting header" approach, where you put the thing that probably works everywhere in a header, and document that someone should probably check it before compiling the code on any freakish implementations. Compared with what they normally have to do to get anybody's code to work, they'll happily live with that.]

    0 讨论(0)
  • 2020-12-06 06:40

    Signed max:

    #define GENERIC_S_MAX(stype) ((stype) ((1ULL << ((sizeof(stype) * 8) - 1)) - 1ULL))
    

    Assuming your system uses two's complement, the signed min should be:

    #define GENERIC_S_MIN(stype) ((stype) -1 - GENERIC_S_MAX(stype))
    

    These should be totally portable, except that long long is technically a compiler extension in C89. This also avoids the undefined behavior of over/underflowing a signed integer.

    0 讨论(0)
提交回复
热议问题