if (0!=(~0xFF)) 条件应该不成立的怎么还会执行的
#include<REGX52.H>unsigned char i,j,k;
void main(void)
{
j=0;
k=~0xFF;
if (0!=(~0xFF)) //左边是0 右边也是0 应该是相等的 条件不成立不执行i++的
{
i++;//但还是执行这了
}
if (j!=k) //都是0,条件不成立
{
i++; //这次就不执行的
}
while (1);
} 数据类型
if(0!=(~(unsigned char )0xff)) 查书,C标准,典型问题:整型类型提升。
0 != (~0xFF) 的完整描述: (int的0) != ~(int的0xFF)。0和0xFF都是int型。假定int = 16bit;于是 int 0 != int 0xFF00 => True。
语句k = ~0xFF,有: k = (unsigned char)(~ (int 0xFF)) => k = (uchar)(int 0xFF00) => k = 0.
j != k 标准C为:(int)j != (int)k 所以相等。 试了下还是执行的啊 回复【1楼】sharpufo风生水起月皎白
数据类型
if(0!=(~(unsigned char )0xff))
-----------------------------------------------------------------------
还是错的。。。。
if(0 != (unsigned char)( ~0xFF)) sorry,我也是随手一写,想到是类型的问题,不过忘了次序的问题。
应该是楼上这样,把(~0xff)类型转化为unsigned char 类再来与0比较.
int 0与unsigned char 0 比较是相等的,会把后者也转化为 int 0. 直接查看汇编代码分析分析不就行了。 回复【2楼】dr2001
-----------------------------------------------------------------------
讲的很详细啊....谢了...上次貌似问过一次了也是类型的问题....这次又忘了,汗
不过我没一本C语言的书....查也没的查... 回复【6楼】eefans
-----------------------------------------------------------------------
分析了..但搞不懂为什么编译成那样了 涨知识了 另外,如果编译器开启了优化
if (0!=(~0xFF)) //左边是0 右边也是0 应该是相等的 条件不成立不执行i++的
{
i++;//但还是执行这了
}
会被直接优化成
i++; 51 处理器 怎么会默认是整形? 翻出 keil 来编译了一下
int main()
{
unsigned char k,f,g,h;
k=~0XFF;
f=0X00;
g=0;
h=0;
if(0!=k)
{
k++;
}
if(0!=f)
{
f++;
}
if(0!=g)
{
g++;
}
if(0!=~0XFF)
{
h++;
}
}
以上代码 统统符合逻辑
编译后的代码自行参阅
C:0x0000 020010 LJMP C:0010
3: int main()
4: {
5: unsigned char k,f,g,h;
6: k=~0XFF;
C:0x0003 E4 CLR A
C:0x0004 FF MOV R7,A
7: f=0X00;
C:0x0005 FE MOV R6,A
8: g=0;
C:0x0006 FD MOV R5,A
9: h=0;
10:
11: if(0!=k)
C:0x0007 6001 JZ C:000A
12: {
13: k++;
C:0x0009 0F INC R7
14: }
15: if(0!=f)
C:0x000A EE MOV A,R6
C:0x000B 6001 JZ C:000E
16: {
17: f++;
C:0x000D 0E INC R6
18: }
19: if(0!=g)
C:0x000E ED MOV A,R5
20: {
C:0x000F 22 RET
C:0x0010 787F MOV R0,#0x7F
C:0x0012 E4 CLR A
C:0x0013 F6 MOV @R0,A
C:0x0014 D8FD DJNZ R0,C:0013
C:0x0016 758107 MOV 0x81,#0x07
C:0x0019 020003 LJMP main(C:0003) 记住(标准C规则):
1.char,usnigned char,signed char本质上没有逻辑,算术运算,char,usnigned char,signed char本质上并不能直接参与运算。
2.所有的算术与逻辑操作符,都要求操作数至少是int。
3.char,usnigned char,signed char参与运算,实际上是把char,usnigned char,signed char先转换成int,或者unsigned int,再再与运算。(C标准里面,这个规则叫整型提升)。
4.C语言所有字面值整型常量,都有自己的类型,而且至少为int。
实际上,绝大大部分编译器,都是遵守上边的规则的。
举例:
1.if (0!=(~0xFF))
0,0xff,不要错误地认为0,0xff的类型是unsigned char,或者没有类型。
实际上所有字面值整型常量,都有自己的类型,这里为int。
2.if (0!=(~(unsigned char)0xFF))
不要错误地认为~unsigned char结果还是unsigned char。
实际上,unsigned char并不能直接进行~运算,需要先提升至int才能运算。
而且~运算符也要有操作数必须至少是int。
这个unsigned char转换没用,因为char参与运算,总是会被提升,至少为int。
3.long a=10*10000; (假定int是16位)
不要错误地认为,a的结果是100000,实际上结果为-31072
原因C语言所有字面值整型常量,都有自己的类型,而且至少为int,这里10和10000都是int型,
而int与int相乘,结果还是int,如果有益出,溢出会被丢弃。10*10000结果为-31072。 回复【13楼】CC2530 上官金虹
记住(标准c规则):
1.char,usnigned char,signed char本质上没有逻辑,算术运算,char,usnigned char,signed char本质上并不能直接参与运算。
2.所有的算术与逻辑操作符,都要求操作数至少是int。
3.char,usnigned char,signed char参与运算,实际上是把char,usnigned char,signed char先转换成int,或者unsigned int,再再与运算。(c标准里面,这个规则叫整型提升)。
4.c语言所有字面值整型常量,都有自己的类型,而且至少为int。
实际上,绝大大部分编译器,都是遵守上边的规则的。
举例:
1.if (0!=(~0xff))
0,0xff,不要错误地认为0,0xff的类型是unsigned char,或者没有类型。
实际上所有字面值整型常量,都有自......
-----------------------------------------------------------------------
这是 Keil C Keil C也是遵守这个规则,
ls的把 unsigned char k,f,g,h ; 放到main函数外面再试试 或者把优化等级设置成0也能看到效果 因为变类型是unsigned char中间运算结果即使是int,也会转换成unsigned char.
比如:
unsigned char k,f;
f=0xff;
k=~f;
虽然~f的结果并不为0,但是在把~f赋值给k的时候,已经自动转成unsigned char,
相当于k=(unsigned char)(~0xff);
所有得到结果k为0,但这并不表示~0xff结果为0. 回复【16楼】Jason022
或者把优化等级设置成0也能看到效果
-----------------------------------------------------------------------
按你的方法试了一下,是这样,想了想觉得应该是32bit交叉编译时编译器的处理问题,因为试过0XFFFFFF,0XFFFFFFFF,凡是奇数字节都被认为是真,另如果在8位系统编译,我就不信还是真 mark #include<REGX52.H>
unsigned int R; //R是整型
unsigned char i,j,k;
void main(void)
{
j=0;
k=0xFF; //K=FF
R = ~0xFF; //这时R的结果是FF00 整型提升了
R = ~j; //j为0 R结果为FFFF
R = ~k; //k为FF, R结果为FF00 说明char被整型提升了
R=0;
if (0!=~k) //~k的结果应该为FF00 就是左右的结果不一样 条件应该是成立的
{
i++; //但没有执行这 说明~k的结果为0 两边相等的才条件不成立 说明没有被整型提升
}
if (R!=~k) //R为0右边~k为FF00
{
i++;//这次执行了 ,说明右边~k应该就是等于FF00了
}
//什么时候会被整型提升看来还与另一个比较的数有关
//if (R!=~k)R为int 右边比较时右边就整型提升成了FF00
//但if (0!=~k) 左边的0也应该认为是整型(楼上的帖子说明了) 右边也应该整型提升才对 实际没有整型提升
//晕了...
while (1);
} 楼上的几位都讲的很详细,学习了,多谢 Keil C51的话,可以使用NOINTPROMOTE关闭整型提升,提升一些性能。
参见:
http://www.keil.com/support/man/docs/c51/c51_intpromote.htm
http://www.keil.com/support/man/docs/c51/c51_nointpromote.htm
http://www.keil.com/support/docs/1754.htm
如果专注于Keil C51平台,这样做没有问题,若还要关注其它的平台,这样做就要斟酌了,搞混的可能性较大(这是C语言中的一个大地雷)。
不过一个好习惯就是完全不要依赖编译器整型提升: 每次使用字面量时都强制指定其类型。 #include<REGX52.H>
unsigned int R; //R是整型
unsigned char i,j,k;
void main(void)
{
j=0;
k=0xFF; //K=FF
if (j!=~0xFF) //右边被整型成FF00
{
i++; //所以执行,
}//~0xFF 证明提升的
if (k!=~0) //那现在右边应该是FFFF 左边K为FF
{
i++;//(没执行)也不等那应该要执行的,现在却没执行 ....那只能说是有时候整型提升 有时候不提升
}// ~0 没提升 就是FF
k=0xFE;
if (k!=~1) //那现在右边应该是FFFE
{
i++;//(没执行)
}//~1 没提升 就是FE
k=0x01;
if (k!=~0xFE) //那现在右边应该是FF01
{
i++;//执行的
}//~0xFE 提升的
//就算一样的写法,只是右边的数值大小不一样时,居然有的提升有的不提升,,实在是晕了
while (1);
} 回复【23楼】jsjjccc
#include<regx52.h>
unsigned int r; //r是整型
unsigned char i,j,k;
void main(void)
{
j=0;
k=0xff; //k=ff
if (j!=~0xff) //右边被整型成ff00
{
i++; //所以执行,
}//~0xff 证明提升的
if (k!=~0) //那现在右边应该是ffff 左边k为ff
{
i++;//(没执行)也不等那应该要执行的,现在却没执行 ....那只能说是有时候整型提升 有时候不提升
}// ~0 没提升 就是ff
k=0xfe;
if (k!=~1) //那现在右边应该是fffe
{
i++;//(没执行)
}//~1 没提升 就是fe
k=0x01;
if (k!=~0xfe) //那现在右边应该是ff01
......
-----------------------------------------------------------------------
KEIL C没有遵守标准C。
楼主换其他编译器试验。
比如,IAR,GCC,或者KEIL MDK FOR ARM(不是KEIL C51).
或者用VC,C++Builder试验。
只不过注意32位机int是32位。 经简单测试,对常数,有不进行整型类型提升;进行整型类型提升。
这样的话,应该是Keil的一个Bug;或者Keil没有按照标准C实现。 好贴,有学到了点东西! 右边也是0
you need to read about type promotion in a good C book.
页:
[1]