簡體   English   中英

C強制轉換和字符簽名

[英]C cast and char signedness

所以最近,我讀了一個關於C中三種不同類型的問題,char / unsigned char / signed char。 我現在遇到的問題到目前為止還沒有經歷過(我的程序可以在所有經過測試的計算機上正常工作,並且只針對低端字節序(基本上是所有使用Windows / Linux的現代台式機和服務器,對嗎?)。我定義用於保存“字符串”(當然不是真正的字符串)作為臨時變量的數組,例如,沒有在堆棧中添加其他字符,我只是重用了像array [0]這樣的成員。一個char總是會被簽名的事實,直到今天我讀到它實際上取決於實現,如果我現在有一個char並給它賦一個負值會發生什么?

char unknownsignedness = -1;

如果我寫

unsigned char A = -1;

我認為C樣式轉換將僅重新解釋位,並且A表示為無符號類型的值將變得不同。 我對這些C-Style強制轉換僅僅是對位的重新解釋嗎? 我現在指的是已簽名的<->未簽名轉換。

因此,如果實現中的char為unsigned,我的程序會停止按預期運行嗎? 如果我現在做的話,取最后一個變量

if (A == -1)

我現在正在將無符號字符與有符號字符值進行比較,因此這將只是比較那些不關心符號性的位,還是會返回假值,因為顯然A不能為-1? 我很困惑在這種情況下會發生什么。 這也是我最大的擔憂,因為我經常使用這種字符。

以下代碼顯示No

#include <stdio.h>

int
main()
{
    unsigned char a;

    a = -1;

    if(a == -1)
        printf("Yes\n");
    else
        printf("No\n");

    return 0;
}

代碼a = -1分配一個實現定義值到a ; 在大多數計算機上,a將為255。測試a == -1unsigned charint進行比較,因此適用通常的升級規則; 因此,它被解釋為

`(int)a == -1`

由於a為255, (int)a仍為255,並且測試得出false。

unsigned char a = -1;

ISO / IEC 9899:1999在6.3.1.3/2中說:

如果新類型是無符號的,則通過重復添加或減去比新類型可表示的最大值多一個值來轉換該值,直到該值在新類型的范圍內為止

我們將(UCHAR_MAX+1)加到-1一次,結果是UCHAR_MAX ,這顯然在unsigned char范圍內。

如果(a == -1)

6.3.1.8/1中有一段很長的篇幅:

如果兩個操作數具有相同的類型,則無需進一步轉換。

否則,如果兩個操作數都具有符號整數類型或都具有無符號整數類型,則將具有較小整數轉換等級的操作數轉換為具有較大等級的操作數的類型。

否則,如果具有無符號整數類型的操作數的秩大於或等於另一個操作數的類型的秩,則將帶符號整數類型的操作數轉換為無符號整數類型的操作數的類型。

否則,如果帶符號整數類型的操作數的類型可以表示帶無符號整數類型的操作數的所有值,則帶無符號整數類型的操作數將轉換為帶符號整數類型的操作數的類型。

否則,兩個操作數都將轉換為與帶符號整數類型的操作數類型相對應的無符號整數類型。

unsigned char的等級小於int的等級。

如果int可以表示unsigned char可以的所有值(通常是這種情況),則兩個操作數都將轉換為int ,並且比較返回false

如果int不能表示unsigned char所有值(這在具有sizeof(int)==sizeof(char)罕見機器上可能發生sizeof(int)==sizeof(char) ,則兩者都將轉換為unsigned int-1轉換為UINT_MAX ,該值與UCHAR_MAX相同,並且比較返回true

unsigned char A = -1;

結果為255。賦值或初始化時沒有重新解釋。 -1只是一堆用二進制補碼表示的1位,並且逐字復制了其中的8位。

比較有點不同,因為文字-1int類型。

if (A == -1)

在比較之前會進行提升(隱式強制轉換) (int)A ,因此最終將255與-1進行比較。 不相等。

是的,您必須小心使用純char

我認為這個問題最好通過一個簡單的例子來回答(警告:C ++,但請參見我的解釋):

char c = -1;
unsigned char u = -1;
signed char s = -1;
if (c == u)
        printf("c == u\n");
if (s == u)
        printf("s == u\n");
if (s == c)
        printf("s == c\n");
if (static_cast<unsigned char>(s) == u)
        printf("(unsigned char)s == u\n");
if (c == static_cast<char>(u))
        printf("c == (char)u\n");

輸出:

s == c
(unsigned char)s == u
c == (char)u

C按原樣使用時對值的處理不同,但是您正確的是,強制轉換只會重新解釋這些位。 我在這里使用C ++ static_cast來表明編譯器可以進行此轉換。 在C語言中,只需在括號中添加類型即可進行強制轉換。 沒有編譯器檢查來確保強制轉換在C中是安全的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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