[英]C size_t and ssize_t negative value
size_t
is declared as unsigned int
so it can't represent negative value. size_t
被声明为unsigned int
因此它不能表示负值。
So there is ssize_t
which is the signed type of size_t
right?所以有ssize_t
是size_t
的有符号类型,对吗?
Here's my problem:这是我的问题:
#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
也得到了错误的结果??
In the first case you're assigning to an unsigned type - a
.在第一种情况下,您分配给无符号类型 - a
。 In the second case you're using the wrong format specifier.在第二种情况下,您使用了错误的格式说明符。 The second specifier should be %zd
instead of %zu
.第二个说明符应该是%zd
而不是%zu
。
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
”,而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 interchangeable, not always at least.最后,这两种类型不可互换,至少并非总是如此。 When the size can go past 2^63 bytes/items the difference is clear.当大小可以超过 2^63 字节/项目时,差异就很明显了。 size_t
won't overflow while ssize_t
will. 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 readv()
使用 ssize_t 。
So, ssize_t
is not the signed version of size_t
as there are values in ssize_t
that cannot be mapped on a size_t
(like -1
) and viceversa.因此, ssize_t
不是size_t
的签名版本,因为ssize_t
中的某些值无法映射到size_t
(如-1
),反之亦然。 And library functions either use one type or the other one.库函数要么使用一种类型,要么使用另一种。
Then, to your questions, the two numbers you see differ by 5 units, that's exactly what you'd expect.然后,对于您的问题,您看到的两个数字相差 5 个单位,这正是您所期望的。 What you see is the value of those two variables when seen as unsigned long
.您看到的是这两个变量在被视为unsigned long
时的值。 Try printing them as signed long
( %ld
) instead so you can still see the sign.尝试将它们打印为有signed long
( %ld
),这样您仍然可以看到符号。
... why i got a wrong result also with
ssize_t
?? ...为什么我的ssize_t
也得到了错误的结果??
Use采用
ssize_t b = -30;
printf("%jd\n", (intmax_t) b);
Use a matching specifier, which for a negative ssize_t
is not %zu
nor certainly "%zd"
.使用匹配的说明符,对于负ssize_t
不是%zu
也不是"%zd"
。
How to use “zd” specifier with printf()
?如何在printf()
使用“zd”说明符? . .
ssize_t b = -30;
printf("%zu\n", b); // problem.
ssize_t
does not have a C specified print specifier. ssize_t
没有 C 指定的打印说明符。 C does not even specify ssize_t
. C 甚至没有指定ssize_t
。
Various extensions to C do specify ssize_t
and in a case of Linux, the print specifier also. C 的各种扩展确实指定了ssize_t
,在 Linux 的情况下,也指定了打印说明符。 Linux Programmer's Manual does have: Linux Programmer's Manual确实有:
z: A following integer conversion corresponds to a
size_t
orssize_t
argument", z: 以下整数转换对应于size_t
或ssize_t
参数",
printf("%zd\n", b); // OK for that Linux
POSIX B.2.12 Data Types has POSIX B.2.12 数据类型有
ssize_t
This is intended to be a signed analog ofsize_t
.ssize_t
这旨在成为size_t
有符号模拟。 The wording is such that an implementation may either choose to use a longer type or simply to use the signed version of the type that underliessize_t
.措辞是这样的,实现可以选择使用更长的类型或简单地使用作为size_t
基础的类型的签名版本。
Since ssize_t
may (uncommonly) be wider than size_t
, using "%zd"
could invoke undefined behavior (UB).由于ssize_t
可能(不常见)比size_t
宽,因此使用"%zd"
可能会调用未定义的行为(UB)。 It is simple enough to cast to the widest standard signed type since C99 as intmax_t
and print.将 C99 以来最宽的标准有符号类型转换为intmax_t
并打印非常简单。
printf("%jd\n", (intmax_t) b); // OK for general use
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溢出因为 size_t 是 UNSIGNED,当您尝试将 size_t 设置为 (-val) 时,您会溢出并获得 SIZE_T_MAX - val
for example: size_t val = -20;例如:size_t val = -20; //val == 18446744073709551615 - 20; //val == 18446744073709551615 - 20;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.