[英]C size_t and ssize_t negative value
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
也得到了錯誤的結果??
在第一種情況下,您分配給無符號類型 - a
。 在第二種情況下,您使用了錯誤的格式說明符。 第二個說明符應該是%zd
而不是%zu
。
首先,您應該檢查兩種類型的實際大小。 像下面的代碼片段應該做的事情:
#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
”,而ssize_t
又可以有符號(正或負)值。
如果它們不同,那么較大的將......更大,因此可以容納更大的值。
但最終, ssize_t
和size_t
是兩種不同的類型,用於“談論”大小、長度、內存量等。
前者只是為該值丟棄 1 位,以獲得發出某種錯誤信號所需的符號。
最后,這兩種類型不可互換,至少並非總是如此。 當大小可以超過 2^63 字節/項目時,差異就很明顯了。 size_t
不會溢出而ssize_t
會。
在“正常”情況下,您可以從一個轉換到另一個。 對於我之前提到的情況,您永遠不應該混合使用它們。
作為參考, strlen()
和malloc()
使用size_t
,而read()
和 readv readv()
使用 ssize_t 。
因此, ssize_t
不是size_t
的簽名版本,因為ssize_t
中的某些值無法映射到size_t
(如-1
),反之亦然。 庫函數要么使用一種類型,要么使用另一種。
然后,對於您的問題,您看到的兩個數字相差 5 個單位,這正是您所期望的。 您看到的是這兩個變量在被視為unsigned long
時的值。 嘗試將它們打印為有signed long
( %ld
),這樣您仍然可以看到符號。
...為什么我的
ssize_t
也得到了錯誤的結果??
采用
ssize_t b = -30;
printf("%jd\n", (intmax_t) b);
使用匹配的說明符,對於負ssize_t
不是%zu
也不是"%zd"
。
如何在printf()
使用“zd”說明符? .
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_t
或ssize_t
參數",
printf("%zd\n", b); // OK for that Linux
ssize_t
這旨在成為size_t
有符號模擬。 措辭是這樣的,實現可以選擇使用更長的類型或簡單地使用作為size_t
基礎的類型的簽名版本。
由於ssize_t
可能(不常見)比size_t
寬,因此使用"%zd"
可能會調用未定義的行為(UB)。 將 C99 以來最寬的標准有符號類型轉換為intmax_t
並打印非常簡單。
printf("%jd\n", (intmax_t) b); // OK for general use
溢出因為 size_t 是 UNSIGNED,當您嘗試將 size_t 設置為 (-val) 時,您會溢出並獲得 SIZE_T_MAX - val
例如:size_t val = -20; //val == 18446744073709551615 - 20;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.