12

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??

4

4 回答 4

21

在第一种情况下,您分配给无符号类型 - a。在第二种情况下,您使用了错误的格式说明符。第二个说明符应该%zd代替%zu.

于 2012-08-29T10:01:18.503 回答
1

首先,您应该检查两种类型的实际尺寸。类似下面的代码片段应该做的事情:

#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;
}

在这两种情况下,我都得到 (64bit Linux, GCC v7.2) “8 bytes”,这与 long int 和 long long int 相同,即最大 CPU 原生整数值。

当大小相同(并且它们应该始终相同)时,size_t可以具有“绝对值大 2 倍” ssize_t,而后者又可以具有带符号的(正或负)值。

如果它们不同,那么较大的将是……更大,因此可以容纳更大的值。

但归根结底,ssize_tsize_t两种不同的类型,用于“谈论”大小、长度、内存量等。

前者只是为该值放弃 1 位,以获得发出某种错误信号所需的符号。

最后,这两种类型不可互换,至少并非总是如此。当大小可以超过 2^63 字节/项目时,差异就很明显了。 size_t不会溢出而ssize_t会。

在“正常”情况下,您可以从一个投射到另一个。对于我之前提到的情况,你不应该混合它们。

仅作为参考,两者都strlen()使用malloc()size_t而两者都read()使用readv()ssize_t。

因此,ssize_t 不是的签名版本,size_t因为其中的某些值ssize_t无法映射到size_t(like -1) 上,反之亦然。库函数要么使用一种类型,要么使用另一种。

然后,对于您的问题,您看到的两个数字相差 5 个单位,这正是您所期望的。你看到的是这两个变量的值unsigned long。尝试将它们打印为signed long( %ld),这样您仍然可以看到标志。

于 2017-10-12T13:38:24.830 回答
0

...为什么我也得到了错误的结果ssize_t??

采用

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

使用匹配的说明符,对于否定ssize_t不是 %zu也不是肯定"%zd"的。
如何使用“zd”说明符printf().

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

ssize_t没有 C 指定的打印说明符。C 甚至没有指定ssize_t.

C 的各种扩展确实指定ssize_t了,在 Linux 的情况下,还指定了打印说明符。 Linux程序员手册确实有:

z: 后面的整数转换对应一个size_torssize_t参数",

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

POSIX B.2.12 数据类型

ssize_t这旨在成为 的有符号模拟size_t。措辞是这样的,即实现可以选择使用更长的类型,或者只是使用底层类型的签名版本size_t


由于ssize_tmay(通常)比 宽size_t,因此 using"%zd"可能会调用未定义的行为(UB)。转换为自 C99 以来最广泛的标准有符号类型intmax_t并打印很简单。

printf("%jd\n", (intmax_t) b);  // OK for general use
于 2019-01-21T16:07:54.203 回答
-4

当您尝试将 size_t 设置为 (-val) 时溢出,因为 size_t 是 UNSIGNED,您会溢出并获得 SIZE_T_MAX - val

例如:size_t val = -20;//val == 18446744073709551615 - 20;

于 2016-11-22T18:38:38.763 回答