C size_t和ssize_t负值

时间:2021-11-08 09:14:54

size_t is declared as unsigned int so it can't represent negative value.
So there is ssize_t which is the signed type of size_t right?
Here's my problem:

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

why i got:

为什么我得到:

18446744073709551591
18446744073709551586

as result?
I know that with size_t this could be possible because it is an unsigned type but why i got a wrong result also with ssize_t??

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

3 个解决方案

#1


19  

In the first case you're assigning to an unsigned type - a. In the second case you're using the wrong format specifier. The second specifier should be %zd instead of %zu.

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

#2


0  

First of all you should check the actual size of the two types. Something like the following snippet should do:

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

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

I get (64bit Linux, GCC v7.2) "8 bytes" in both cases, which is the same as long int and long long int, the maximum CPU-native integer value.

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

When the sizes are the same (and they should always be), size_t can have "2x larger absolute values" than ssize_t which, in turn, can have signed (that's either positive or negative) values.

当大小相同(并且它们应该始终是)时,size_t可以具有比ssize_t大2倍的绝对值,而ssize_t又可以具有签名(即正或负)值。

If they were different, then the larger one would be ... larger and could thus accommodate for larger values.

如果它们不同,则较大的那个会更大,因此可以容纳更大的值。

But in the end, ssize_t and size_t are two different types used to "talk" about sizes, lengths, amounts of memory and so on.

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

The former is just ditching 1 bit for the value in order to gain the sign needed to signal some sort of error.

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

Finally, the two types are not interchangeble, not always at least. When the size can go past 2^63 bytes/items the difference is clear. size_t won't overflow while ssize_t will.

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

Under "normal" circumstances you can cast from one to the other one. For the cases I mentioned earlier, you should never mix them.

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

Just as a reference, both strlen() and malloc() use size_t, while both read() and readv() use ssize_t.

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

So, ssize_t IS NOT the signed version of size_t as they have non-overlapping realms.

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

Then, to your questions, the two numbers you see differ by 5 units, that's exaclty what you'dexpect. What you see is the value of thsoe two variables when seen as "unsigned long". Try printing them as "signed long" (%ld) instead.

那么,对于你的问题,你看到的两个数字相差5个单位,这是你所期望的。你看到的是当被视为“无符号长”时两个变量的值。尝试将它们打印为“签名长”(%ld)。

#3


-4  

Overflow coz size_t is a UNSIGNED when you try to set size_t as (-val) you get overflow and get SIZE_T_MAX - val

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

for example: size_t val = -20; //val == 18446744073709551615 - 20;

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

#1


19  

In the first case you're assigning to an unsigned type - a. In the second case you're using the wrong format specifier. The second specifier should be %zd instead of %zu.

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

#2


0  

First of all you should check the actual size of the two types. Something like the following snippet should do:

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

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

I get (64bit Linux, GCC v7.2) "8 bytes" in both cases, which is the same as long int and long long int, the maximum CPU-native integer value.

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

When the sizes are the same (and they should always be), size_t can have "2x larger absolute values" than ssize_t which, in turn, can have signed (that's either positive or negative) values.

当大小相同(并且它们应该始终是)时,size_t可以具有比ssize_t大2倍的绝对值,而ssize_t又可以具有签名(即正或负)值。

If they were different, then the larger one would be ... larger and could thus accommodate for larger values.

如果它们不同,则较大的那个会更大,因此可以容纳更大的值。

But in the end, ssize_t and size_t are two different types used to "talk" about sizes, lengths, amounts of memory and so on.

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

The former is just ditching 1 bit for the value in order to gain the sign needed to signal some sort of error.

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

Finally, the two types are not interchangeble, not always at least. When the size can go past 2^63 bytes/items the difference is clear. size_t won't overflow while ssize_t will.

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

Under "normal" circumstances you can cast from one to the other one. For the cases I mentioned earlier, you should never mix them.

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

Just as a reference, both strlen() and malloc() use size_t, while both read() and readv() use ssize_t.

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

So, ssize_t IS NOT the signed version of size_t as they have non-overlapping realms.

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

Then, to your questions, the two numbers you see differ by 5 units, that's exaclty what you'dexpect. What you see is the value of thsoe two variables when seen as "unsigned long". Try printing them as "signed long" (%ld) instead.

那么,对于你的问题,你看到的两个数字相差5个单位,这是你所期望的。你看到的是当被视为“无符号长”时两个变量的值。尝试将它们打印为“签名长”(%ld)。

#3


-4  

Overflow coz size_t is a UNSIGNED when you try to set size_t as (-val) you get overflow and get SIZE_T_MAX - val

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

for example: size_t val = -20; //val == 18446744073709551615 - 20;

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