Ç为size_t和ssize_t供负值(C size_t and ssize_t negative

2019-07-31 06:18发布

size_t声明为unsigned int ,因此它不能代表负值。
所以ssize_t这是有符号的类型size_t吧?
这里是我的问题:

#include <stdio.h>
#include <sys/types.h>

int main(){
size_t a = -25;
ssize_t b = -30;
printf("%zu\n%zu\n", a, b);
return 0;
}

为什么我的了:

18446744073709551591
18446744073709551586

结果?
我知道,与size_t这可能是可能的,因为它是一个无符号的类型,但为什么我得到一个错误的结果也ssize_t

Answer 1:

在第一种情况下,你要指定一个无符号的类型- a 。 在第二种情况下,你使用了错误的格式说明。 第二符应该是%zd代替%zu



Answer 2:

首先,你应该检查这两种类型的实际大小。 如下面的代码片段的东西应该做的:

#include <stdio.h>
#include <unistd.h>

int main() {
  printf( "sizeof(  size_t ) = %d bytes\n",(int) sizeof( size_t) );
  printf( "sizeof( ssize_t ) = %d bytes\n",(int) sizeof( ssize_t) );
  return 0;
}

我得到(64位Linux中,GCC V7.2)在这两种情况下“8个字节”,这是相同的长整型,长长整型,最大CPU天然整数值。

当该尺寸是相同的(他们应该永远是), size_t可以有“2X更大的绝对值”比ssize_t ,这反过来,可以签署(这是正或负)值。

如果他们是不同的,那么大的一个是...更大,从而可以容纳较大的值。

但最终, ssize_tsize_t是用于“交谈”关于尺寸,长度,内存数量等两种不同类型。

前者只是开沟1位的值,以获得信号某种错误所需要的迹象。

最后,这两种类型是不能互换的,并不总是最少。 当大小可以走过去的2 ^ 63字节/项目的差别是显而易见的。 size_t不会溢出,同时ssize_t会。

在“正常”的情况下,你可以从一个转换为另一种。 对于我前面提到的情况下,你不应该混合。

只是作为参考,双方strlen()malloc()使用size_t ,同时兼具read()readv()使用ssize_t供。

因此, ssize_t 不是签名版本size_t ,因为他们有不重叠的领域。

然后,你的问题,你看这两个数字5个单位不同,这正是你所期望。 你看到的是,当所看到这两个变量的值unsigned long 。 尝试打印他们为signed long%ld )来代替。



Answer 3:

...为什么我得到一个错误的结果也ssize_t

使用

ssize_t b = -30;
printf("%jd\n", (intmax_t) b); 

使用匹配的说明,这对于一个负ssize_t 不是 %zu

ssize_t b = -30;
printf("%zu\n", b);  // problem.

ssize_t没有一个C指定的打印符。 C不连指定ssize_t

到C不同的扩展都指定ssize_t而在Linux,打印符还的情况。 Linux的程序员手册确有:

Z:阿以下整数的转换对应于size_tssize_t参数”,

printf("%zd\n", b);  // OK for that Linux

POSIX B.2.12数据类型有

size_t这是为了成为一个符号模拟size_t 。 这种写法是这样的实现可能要么选择使用较长的类型或者简单地使用构成了这一类型的签名版本size_t


由于ssize_t可(罕见)比更宽size_t ,使用"%zd"可以调用未定义的行为 (UB)。 这是很简单的转换为最广泛的标准符号的类型,因为C99的intmax_t和打印。

printf("%jd\n", (intmax_t) b);  // OK for general use


Answer 4:

溢出堂妹为size_t是无符号,当您尝试设置为size_t为(-Val)你得到溢出,并得到SIZE_T_MAX - VAL

例如:为size_t VAL = -20; // VAL == 18446744073709551615 - 20;



文章来源: C size_t and ssize_t negative value
标签: c size-t