C 将sizeof()的结果分配给ssize\u t

C 将sizeof()的结果分配给ssize\u t,c,posix,sizeof,C,Posix,Sizeof,我碰巧需要将sizeof(x)的结果与ssize\t进行比较 当然,GCC给出了一个错误(我很幸运(我使用了-Wall-Wextra-Werror),我决定执行一个宏来获得签名版本的sizeof() 然后我可以这样使用它: for (ssize_t i = 0; i < ssizeof(x); i++) ssize_t result = read(fd, buf, count); if (result != -1) { size_t offset = (size_t) resul

我碰巧需要将
sizeof(x)
的结果与
ssize\t
进行比较

当然,GCC给出了一个错误(我很幸运(我使用了
-Wall-Wextra-Werror
),我决定执行一个宏来获得签名版本的
sizeof()

然后我可以这样使用它:

for (ssize_t i = 0; i < ssizeof(x); i++)
ssize_t result = read(fd, buf, count);
if (result != -1) {
    size_t offset = (size_t) result;
    /* handle success */
} else {
    /* handle failure */
}
(signed_number < 0 || (size_t) signed_number < unsigned_number))
for(ssize\u t i=0;i
问题是,我是否可以保证
SSIZE\u MAX>=SIZE\u MAX
?我想很遗憾,这永远不会是真的

或者至少是
sizeof(ssize\u t)=sizeof(size\u t)
,这将减少一半的值,但仍然足够接近

我在POSIX文档中没有找到
ssize\u t
size\u t
之间的任何关系

相关问题:


请注意,您实际上不能这样做

x86Linux中可能最大的对象大小略小于0xB0000000,而
SSIZE\u T\u MAX
则为0x7FFFFFFF

我没有检查
read
和stuff是否真的可以处理最大的对象,但如果可以,它的工作原理如下:

for (ssize_t i = 0; i < ssizeof(x); i++)
ssize_t result = read(fd, buf, count);
if (result != -1) {
    size_t offset = (size_t) result;
    /* handle success */
} else {
    /* handle failure */
}
(signed_number < 0 || (size_t) signed_number < unsigned_number))
您可能会发现
libc
已损坏。如果是这样的话,如果内核是好的,这将起作用:

ssize_t result = sys_read(fd, buf, count);
if (result >= 0 || result < -256) {
    size_t offset = (size_t) result;
    /* handle success */
} else {
    errno = (int)-result;
    /* handle failure */
}
ssize\u t result=sys\u read(fd、buf、count);
如果(结果>=0 | |结果<-256){
大小\u t偏移=(大小\u t)结果;
/*成功*/
}否则{
errno=(int)-结果;
/*处理失败*/
}

不能保证
SSIZE\u MAX>=SIZE\u MAX
。事实上,这种情况不太可能发生,因为
size\u t
ssize\u t
可能是相应的无符号和有符号类型,所以(在所有实际体系结构上)
size\u MAX>ssize\u MAX
。将无符号值强制转换为无法保存该值的有符号类型是未定义的行为。所以从技术上讲,你的宏是有问题的

实际上,至少在64位平台上,如果要转换为
ssize\t
的值是实际存在的对象的大小,则不太可能遇到问题。但是如果对象是理论上的(例如
sizeof(char[3][1all=Q
),那么
(size\u t)(P-Q)
是指针之间在数学上正确的差异,即使减法溢出。当然,依赖于此类扩展的代码不会完全可移植,但如果扩展足够常见,这可能不是问题


最后一点,使用-1作为错误指示(在
ssize_t
中)和指针减法(在
ptrdiff_t
中)的可能可强制执行结果的模糊性如果
size\u t
与指针一样大,则在实践中不太可能出现。如果
size\u t
与指针一样大,则
P-Q
的数学正确值可以是
(size\u t)(-1)
(又称
size\u MAX
)如果
P
Q
引用的对象的大小为
size\u MAX
,假设
size\u t
与指针的宽度相同,则意味着该对象加上下面的字节占据了所有可能的指针值。这与某些指针值(
NULL
的要求相矛盾与任何有效地址不同,因此我们可以得出结论,一个对象的真正最大大小必须小于
size\u MAX
我将把这看作是一个X-Y问题。问题是,您希望将一个有符号的数字与一个无符号的数字进行比较。而不是将
sizeof
的结果强制转换为
ssize\t
,您应该检查您的
ssize\u t
值是否小于零。如果小于零,则您知道它小于您的
size\u t
值。如果不小于零,则可以将其强制转换为
size\u t
,然后进行比较

例如,这里有一个比较函数,如果有符号数小于无符号数,则返回
-1
;如果相等,则返回0;如果有符号数大于无符号数,则返回1:

int compare(ssize_t signed_number, size_t unsigned_number) {
    int ret;
    if (signed_number < 0 || (size_t) signed_number < unsigned_number) {
        ret = -1;
    }
    else {
        ret = (size_t) signed_number > unsigned_number;
    }
    return ret;
}
int比较(ssize\u t有符号编号、size\u t无符号编号){
int ret;
if(带符号的|u数<0 | |(大小)带符号的|u数<无符号的|u数){
ret=-1;
}
否则{
ret=(大小)有符号数>无符号数;
}
返回ret;
}

如果您想要的只是相当于
ssize\u t的POSIX类型,那么它不是C标准的一部分。POSIX定义ssize\u t必须能够处理区间[-1,ssize\u MAX]内的数字,因此原则上它甚至不需要是一个普通的有符号类型。这个有点奇怪的定义的原因是,唯一使用ssize_t的地方是作为读/写/等函数的返回值

实际上,它始终是一个与size_t大小相同的普通有符号类型。但是,如果您想真正学究化您的类型,您不应该将其用于处理IO系统调用的返回值以外的其他用途。对于一般的“指针大小”有符号整数类型,C89定义了ptrdiff_t。实际上,它与ssize_t相同


另外,如果您查看,您将看到对于'nbyte'参数,它表示“如果nbyte的值大于{SSIZE_MAX},则结果是由实现定义的”。因此,即使大小能够表示大于SSIZE_MAX的值,使用大于IO系统调用的值也是由实现定义的行为(如前所述,这是唯一使用ssize_t的地方)等等。

然后我猜答案是我问的问题没有保证,但同时这证明了POSIX的
ssize\u t
ssize\u MAX
中有一个bug,对吧?
ssize\u t
应该能够容纳尽可能大的对象的大小,否则就没用了。因此,IMHO,
(sizeof(ssize\t)>sizeof(size_t))&&(SSIZE_MAX>=size_MAX)
对于该类型,这应该是正确的