C语言枚举类型的疑惑,高手进

qiuhui00 2012-03-07 03:53:34
一直以来都以为C语言的枚举类型是有符号整形,今天无意中发现好像不是这么简单。

我先写了个简单的测试程序如下

#include <stdio.h>

int main(void)
{
enum liquid {OUNCE = 1, CUP = 8, PINT = 16,
QUART = 32, GALLON = 128};

enum liquid jar;
jar = -1;

printf("%d\n", jar);
if (jar < 0)
{
printf("less than zero\n");
}

return 0;
}


运行的结果是:
-1
从上面的结果来看,枚举类型似乎是用无符号整形来表示的.因为如果是用有符号整形来表示的话, 上面程序运行的结果应该是
-1
less than zero

而如果把程序做一个小小的修改,如下
#include <stdio.h>

int main(void)
{
/* OUNCE改成了-1 */
enum liquid {OUNCE = -1, CUP = 8, PINT = 16,
QUART = 32, GALLON = 128};

enum liquid jar;
jar = -1;

printf("%d\n", jar);
if (jar < 0)
{
printf("less than zero\n");
}

return 0;
}


运行的结果是
-1
less than zero
这个结果似乎又说明枚举类型不是用无符号整形来表示的。那到底实际情况是怎么样呢?我推测应该是跟枚举类型的定义有关。
因为在第一段代码中,enum liquid的所有枚举值都是非负数,非负数可以用无符号整形来表示,于是编译器就把enum liquid类型的jar
用无符号整形来表示,然后就得到了上面第一个测试结果。而在第二段代码中, enum liquid的枚举值中包含了-1这个负数, 不能用无符号整形来表示,于是编译器就用有符号
整形来表示jar, 第二个测试结果似乎也证实了这一点。
网上搜了一下,似乎没有对这个问题很好的解释,期待高手的解释。
...全文
1324 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
AnyStretch 2014-11-09
  • 打赏
  • 举报
回复
在32位机器中,枚举类型默认为4个字节的无符号类型,所以-1会变为2^32-1。但是如果向示例二这样的话,枚举类型又会为有符号类型,所以条件自然成立。
qiuhui00 2012-03-07
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 saleayas 的回复:]

However, converting an integer to an enumerator requires an explicit cast, and the results are not defined if the integer value is outside the range of the defined enumeration.
[/Quote]
谢谢啊,原来是这样
Saleayas 2012-03-07
  • 打赏
  • 举报
回复
However, converting an integer to an enumerator requires an explicit cast, and the results are not defined if the integer value is outside the range of the defined enumeration.
  • 打赏
  • 举报
回复
asm
flyrack 2012-03-07
  • 打赏
  • 举报
回复
给枚举类型赋值是很不厚道的行为 会导致编译器在风中凌乱
如此美丽的你 2012-03-07
  • 打赏
  • 举报
回复
根据C标准的规定,枚举常量的类型为 int,枚举变量的类型应该与 char、有符号或无符号整型兼容。因此,枚举变量可以接受 char、有符号或无符号整型数,而不限于仅从此枚举类型所定义的枚举常量中取值。由于上述原因,在C语言中无法从语法上保证枚举变量只能在定义的枚举成员中取值,只能由程序员自身保证不使用除枚举成员之外的值。
在第一例中:jar=-1 确确实实是将jar的内存中值变为了-1,但在编译器的记忆中jar只有1,8,16,32,128等值。所以在用if判断时,编译器认为jar的值仍是大于零的。
第二个理所应当就不解释了。

赵老师:
不要纠结各种常量了,这个世界上唯一不变的就是变化。用API WriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢!
qiuhui00 2012-03-07
  • 打赏
  • 举报
回复
但是我想知道编译器是把它当作无符号整形来处理还是有符号整形来处理,或者是看情况?
东莞某某某 2012-03-07
  • 打赏
  • 举报
回复
enum是一种数据类型经常作为常量来使用,enum变量的存储宽度(sizeof(...))是编译器规定的,比如CLR中的enum可指定type:enum [: type] {enum-list}
qiuhui00 2012-03-07
  • 打赏
  • 举报
回复
我这么赋值,原本其实就是想知道如果给枚举类型赋个负值,会出现什么情况,所以才有了后面的疑惑,我并不是故意要写错
面包大师 2012-03-07
  • 打赏
  • 举报
回复
允许有负数,可是,你的第一个程序呢?最小的才是0,你给他赋值个-1,是不是明知是错的,还要去做呢?
qiuhui00 2012-03-07
  • 打赏
  • 举报
回复
为什么说是错的?枚举类型值当中不能有负数吗?
面包大师 2012-03-07
  • 打赏
  • 举报
回复
不知道为什么,很多人总是去纠结错误的东西

70,034

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧