C size_t和ssize_t负值

时间:2012-08-29 09:59:50

标签: c size-t

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 个答案:

答案 0 :(得分:19)

在第一种情况下,您指定的是无符号类型 - a。在第二种情况下,您使用了错误的格式说明符。第二个说明符应为%zd而不是%zu

答案 1 :(得分: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;
}

在两种情况下,我得到(64位Linux,GCC v7.2)“8字节”,这与long int和long long int相同,是最大的CPU本机整数值。

当尺寸相同时(并且它们应该始终如此),size_t可以具有比ssize_t“绝对值大2倍的”,而ssize_t反过来可以签名(正面或负面) )值。

如果它们不同,那么较大的那个会更大......因此可以适应更大的值。

但最后,size_tsize_t是用于“谈论”大小,长度,内存量等的两种不同类型。

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

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

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

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

因此,size_t 不是 unsigned long的签名版本,因为它们具有非重叠的领域。

然后,对于您的问题,您看到的两个数字相差5个单位,这正是您所期望的。您看到的是signed long时这两个变量的值。请尝试将其打印为%ld. └── dira ├── a ├── b ├── c └── dirb )。

答案 2 :(得分:0)

  

...为什么我也用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 Programmer's Manual确实具有:

  

z:以下整数转换对应于size_tssize_t参数“,

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

POSIX B.2.12 Data Types具有

  

size_t旨在作为size_t的带符号类似物。措辞是这样的,实现可以选择使用更长的类型,也可以简单地使用位于size_t之下的类型的带符号版本。


由于ssize_t可能(通常)比size_t宽,因此使用"%zd"可以调用未定义的行为(UB)。将C99转换为C intmax_t之后最宽的标准有符号类型并进行打印非常简单。

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

答案 3 :(得分:-4)

溢出coz size_t是UNSIGNED 当您尝试将size_t设置为(-val)时 你得到溢出并获得SIZE_T_MAX - val

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