簡體   English   中英

C size_t 和 ssize_t 負值

[英]C size_t and ssize_t negative value

size_t被聲明為unsigned int因此它不能表示負值。
所以有ssize_tsize_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_tsize_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_tssize_t參數",

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

POSIX B.2.12 數據類型

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM