這對我來說似乎很奇怪,而且我從未在有關 C 列舉的資源中看到任何關于它的討論。變數a的型別為enum Direction,可以為-1,但a<0為假。我對列舉缺少什么?
#include <stdio.h>
enum Direction {N,W,S,E};
int main()
{
enum Direction a = N;
printf("a is %d\n", a);
a--;
printf("now a is %d\n", a);
printf("but (a<0) is %d\n\n", (a<0));
int b = N;
printf("b is %d\n", b);
b--;
printf("now b is %d\n", b);
printf("and (b<0) is %d\n", (b<0));
return 0;
}
輸出是
a is 0
now a is -1
but (a<0) is 0
b is 0
now b is -1
and (b<0) is 1
uj5u.com熱心網友回復:
列舉的底層型別是實作定義的整數型別,可以表示列舉的所有項。在這里,它可能是char, int, unsigned int(可能是其他)。
您的實作顯然選擇使用unsigned int; 它與與 0 的比較一致(不能為負數),并且您僅將其列印為-1因為在 2-補碼中,-1 具有與“相同寬度的最大無符號”相同的表示形式(這是您擁有的值, 因為無符號 0 減 1 會換成最大值)。
它只列印為-1因為%dprintf的格式,它將它轉換回簽名。但是因為它是未簽名的,所以你應該使用%u.
當您通過創建 int var 將其轉換為有符號整數時,您有一個實際的 int,因此它的行為正確(-1按%dprintf的格式列印)。
uj5u.com熱心網友回復:
這取決于編譯器選擇哪種整數型別與列舉型別兼容。編譯器可以選擇無符號整數型別。
在這份宣告中
printf("now a is %d\n", a);
您正在使用%d為有符號整數型別設計的轉換說明符,盡管列舉可以與無符號整數型別兼容,如果您將使用轉換說明符,%u您將獲得另一個結果。
例如,如果您將列舉常量宣告為具有負值,則編譯器將選擇與列舉兼容的有符號整數型別。
這是兩個演示程式,顯示了差異
#include <stdio.h>
int main( void )
{
enum Direction {N,W,S,E};
enum Direction a = N;
--a;
printf( "a < 0 is %d\n", a < 0 );
}
這個程式的輸出是
a < 0 is 0
編譯器選擇無符號整數型別作為兼容的整數型別。
#include <stdio.h>
int main( void )
{
enum Direction {N = -1, W,S,E};
enum Direction a = W; // W is equal to 0
--a;
printf( "a < 0 is %d\n", a < 0 );
}
這個程式的輸出是
a < 0 is 1
因為編譯器選擇了有符號整數型別作為兼容的整數型別。
形成 C 標準(6.7.2.2 列舉說明符)
4 每個列舉型別應與 char、有符號整數型別或無符號整數型別兼容。型別的選擇是實作定義的,128) 但應該能夠表示列舉的所有成員的值。噸
那就是列舉型別和列舉常量之間存在差異。列舉常量始終具有型別int。但是列舉型別與編譯器選擇的整數型別(有符號或無符號)兼容。
比較printf這個演示程式中的兩個呼叫。
#include <stdio.h>
int main( void )
{
enum Direction {N,W,S,E};
enum Direction a = N;
printf( "a - 1 < 0 is %d\n", a - 1 < 0 );
printf( "N - 1 < 0 is %d\n", N - 1 < 0 );
}
程式輸出在哪里
a - 1 < 0 is 0
N - 1 < 0 is 1
uj5u.com熱心網友回復:
陷阱是列印時的格式說明符a。格式說明符%d可以printf解釋a為有符號整數,無論??它實際上是什么資料型別。但實際上,它是一個無符號整數,并a--導致溢位,即a == 4294967295. 因此a < 0是false。當將此值解釋為有符號整數時,它是 -1。%u列印時嘗試使用as 格式說明符a,您將看到a.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/407556.html
標籤:
