C题:off_t(和其他有符号整数类型)的最小值和最大值 [英] C question: off_t (and other signed integer types) minimum and maximum values

查看:10
本文介绍了C题:off_t(和其他有符号整数类型)的最小值和最大值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我偶尔会遇到一个整数类型(例如 POSIX 有符号整数类型 off_t),如果为它的最小值和最大值设置一个宏会很有帮助,但我不知道如何做一个真正便携的.


对于无符号整数类型,我一直认为这很简单.0 为最小值,~0 为最大值.我已经阅读了几个不同的 SO 线程,这些线程建议使用 -1 而不是 ~0 以实现可移植性.有一些争论的有趣线程在这里:
c++ - 使用安全吗 -1 将所有位设置为真?- 堆栈溢出

但是,即使在阅读了有关此问题的内容后,我仍然感到困惑.另外,我正在寻找同时符合 C89 和 C99 的东西,所以我不知道是否适用相同的方法.假设我有一种 uint_whatever_t.我不能先转换为 0 然后按位补码吗?这样可以吗?:

#define UINT_WHATEVER_T_MAX ( ~ (uint_whatever_t) 0 )


有符号整数类型看起来更难破解.我见过几种不同的可能解决方案,但只有 一个 似乎是可移植的.要么是这样,要么是不正确的.我在搜索 OFF_T_MAX 和 OFF_T_MIN 时发现了它.感谢克里斯蒂安·比尔:

#define MAX_INT_VAL_STEP(t) ((t) 1 <<<(CHAR_BIT * sizeof(t) - 1 - ((t) -1 <1)))#define MAX_INT_VAL(t) ((MAX_INT_VAL_STEP(t) - 1) + MAX_INT_VAL_STEP(t))#define MIN_INT_VAL(t) ((t) -MAX_INT_VAL(t) - 1)[...]#define OFF_T_MAX MAX_INT_VAL(off_t)


我找不到任何关于 C89 中不同允许类型的有符号整数表示的信息,但 C99 在 §J.3.5 中有关于整数可移植性问题的说明:

<块引用>

有符号整数类型是否使用符号和大小表示,二进制补码还是个补码,异常值是否是陷阱表示或普通值(6.2.6.2).

这似乎意味着只能使用这三个列出的有符号数字表示.含义是否正确,上述宏是否与所有三种表示形式兼容?

<小时>其他想法:
如果有填充位,类似函数的宏 MAX_INT_VAL_STEP() 似乎会给出不正确的结果.我想知道有没有办法解决这个问题.

通读 维基百科上的有符号数表示 我发现对于所有三个有符号整数表示任何有符号整数类型的 MAX 将是:
符号位关闭,所有值位打开(全部三个)
它的 MIN 可以是:
符号位打开,所有值位都打开(符号和幅度)
符号位打开,所有值位关闭(1/2 补码)

我想我可以通过这样做来测试符号和大小:

#define OFF_T_MIN ( ( ( (off_t)1 | ( ~ (off_t) -1 ) ) != (off_t)1 ) ?/* 这里的符号和幅度最小值 */:/* 一个和两个在此处补最小值 */)

然后,由于符号和幅度是符号位,并且在这种情况下,所有值位都不会是 off_t 的最小值 ~ (off_t) 0 ?对于一个/两个补码最小值,我需要一些方法来关闭所有值位,但保留符号位.在不知道值位数的情况下不知道如何执行此操作.符号位是否保证总是比最高有效值位高一个?

谢谢,如果这篇文章太长,请告诉我


<小时>

编辑 2010 年 12 月 29 日下午 5 点 EST:
正如 ehemient 在下面得到无符号类型最大值所回答的那样, (unsigned type)-1~0 甚至 ~(unsigned type)0 更正确.据我所知,当您使用 -1 时,它与 0-1 相同,这始终会导致无符号类型的最大值.

此外,由于可以确定无符号类型的最大值,因此可以确定无符号类型中有多少值位.感谢 Hallvard B. Furuseth 在回复 comp.lang.c 上的问题

/* inttype_MAX 或任何 (1<

<块引用>

IMAX_BITS(INT_MAX) 计算 int 中的位数,而 IMAX_BITS((unsigned_type)-1) 计算 unsigned_type 中的位数.无论如何,直到有人实现 4 GB 整数:-)

然而,我的问题的核心仍未得到解答:如何通过宏确定 signed 类型的最小值和最大值.我还在调查这个.也许答案是没有答案.

如果您在大多数情况下没有在 StackOverflow 上查看此问题,则在被接受之前您无法看到建议的答案.建议在 StackOverflow 上查看此问题.

解决方案

我相信我终于解决了这个问题,但解决方案仅在 configure-time 可用,而不是编译时或运行时,所以它仍然不知道.这里是:

HEADERS="#include <sys/types.h>"TYPE="off_t"我=8尽管 : ;做printf "%s
struct { %s x : %d; };
" "$HEADERS" "$TYPE" $i >测试.c$CC $CFLAGS -o/dev/null -c test.c ||休息i=$(($i+1))完毕rm test.c回声 $(($i-1))

想法来自6.7.2.1第3段:

<块引用>

指定位域宽度的表达式应为整数常量具有不超过对象宽度的非负值的表达式如果省略了冒号和表达式,则指定的类型.如果值为零,声明不应有声明符.

如果这能带来在编译时解决问题的任何想法,我会非常高兴.

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 values, but I don't know how to make one that is truly portable.


For unsigned integer types I had always thought this was simple. 0 for the minimum and ~0 for the maximum. I have since read of several different SO threads which suggest using -1 instead of ~0 for portability. An interesting thread with some contention is here:
c++ - Is it safe to use -1 to set all bits to true? - Stack Overflow

However even after reading about this issue I'm still confused. Also, I'm looking for something both C89 and C99 compliant so I don't know if the same methods apply. Say I had a type of uint_whatever_t. Couldn't I just cast to 0 first and then bitwise complement? Would this be ok?:

#define UINT_WHATEVER_T_MAX ( ~ (uint_whatever_t) 0 )


Signed integer types look like they'll be a tougher nut to crack. I've seen several different possible solutions but only one appears to be portable. Either that or it's incorrect. I found it while googling for an OFF_T_MAX and OFF_T_MIN. Credit to Christian Biere:

#define MAX_INT_VAL_STEP(t) 
    ((t) 1 << (CHAR_BIT * sizeof(t) - 1 - ((t) -1 < 1))) 

#define MAX_INT_VAL(t) 
    ((MAX_INT_VAL_STEP(t) - 1) + MAX_INT_VAL_STEP(t))

#define MIN_INT_VAL(t) 
    ((t) -MAX_INT_VAL(t) - 1)

[...]
#define OFF_T_MAX MAX_INT_VAL(off_t) 


I couldn't find anything regarding the different allowable types of signed integer representations in C89, but C99 has notes for integer portability issues in §J.3.5:

Whether signed integer types are represented using sign and magnitude, two’s complement, or ones’ complement, and whether the extraordinary value is a trap representation or an ordinary value (6.2.6.2).

That would seem to imply that only those three listed signed number representations can be used. Is the implication correct, and are the macros above compatible with all three representations?


Other thoughts:
It seems that the function-like macro MAX_INT_VAL_STEP() would give an incorrect result if there were padding bits. I wonder if there is any way around this.

Reading through signed number representations on Wikipedia it occurs to me that for all three signed integer representations any signed integer type's MAX would be:
sign bit off, all value bits on (all three)
And its MIN would be either:
sign bit on, all value bits on (sign and magnitude)
sign bit on, all value bits off (ones/twos complement)

I think I could test for sign and magnitude by doing this:

#define OFF_T_MIN ( ( ( (off_t)1 | ( ~ (off_t) -1 ) ) != (off_t)1 ) ? /* sign and magnitude minimum value here */ : /* ones and twos complement minimum value here */ )

Then as sign and magnitude is sign bit on and all value bits on wouldn't the minimum for off_t in that case be ~ (off_t) 0 ? And for ones/twos complement minimum I would need some way to turn all the value bits off but leave the sign bit on. No idea how to do this without knowing the number of value bits. Also is the sign bit guaranteed to always be one more significant than the most significant value bit?

Thanks and please let me know if this is too long a post



EDIT 12/29/2010 5PM EST:
As answered below by ephemient to get the unsigned type max value, (unsigned type)-1 is more correct than ~0 or even ~(unsigned type)0. From what I can gather when you use -1 it is just the same as 0-1 which will always lead to the maximum value in an unsigned type.

Also, because the maximum value of an unsigned type can be determined it is possible to determine how many value bits are in an unsigned type. Credit to Hallvard B. Furuseth for his IMAX_BITS() function-like macro that he posted in reply to a question on comp.lang.c

/* Number of bits in inttype_MAX, or in any (1<<b)-1 where 0 <= b < 3E+10 */
#define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) /0x3fffffffL %0x3fffffffL *30 
                  + (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4-12/((m)%31+3))

IMAX_BITS(INT_MAX) computes the number of bits in an int, and IMAX_BITS((unsigned_type)-1) computes the number of bits in an unsigned_type. Until someone implements 4-gigabyte integers, anyway:-)

The heart of my question however remains unanswered: how to determine the minimum and maximum values of a signed type via macro. I'm still looking into this. Maybe the answer is there is no answer.

If you are not viewing this question on StackOverflow in most cases you cannot see the proposed answers until they are accepted. It is suggested to view this question on StackOverflow.

解决方案

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
struct { %s x : %d; };
" "$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.

这篇关于C题:off_t(和其他有符号整数类型)的最小值和最大值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆