OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2176|回复: 6

疑惑不解,求助!C语言自动数据类型转换碰到的一个问题

[复制链接]

8

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2019-1-18
在线时间
18 小时
发表于 2019-3-22 16:06:01 | 显示全部楼层 |阅读模式
5金钱
有个关于C语言的数据类型自动转换的问题,代码如下:

#include "reg51.h"  //此代码为在STC89C52上的运行结果
void main(){
    unsigned int retval;
    char a;
    UartInit();
    a=0xc0;
    retval=(a>>6)&0xff; //此处位与的立即数若为0xff,则通过串口输出查看retaval为 0x0003; 若位与运算的立即数为0xfe则结果为 0x00fe; 为何会如此
    UartTxInt(retval);
    while(1){
        ;
    }
}
疑问.png
代码如上所写,即retval=(a>>6)&0xff; 这一句执行后,为何用串口查看retval为0x0003?
按照我的理解,
①首先因为a是char类型,所以在参于运算时首先自动转换为int类型,所以右移6位后数据内容为bit: 1111 1111 1111 1111 ;
②再与立即数0xff进行位与运算,立即数默认为int类型,所以相当于0xffff & 0x00ff ;
③结果即应该为 0x00 ff 才对,但是在单片机上运行的结果却为0x0003 ;
④很诡异的是,如果我将上述语句的0xff 替换成 0xfe, 那么运算的结果就如预期的变成 0x00 fe 了。

因为对C语言的数据类型的自动转换理解还不太到位,所以想请问各位大神上述计算的结果是怎样来的,我的理解哪一步有错误呢,谢谢!

最佳答案

查看完整内容[请看2#楼]

你把 char a; 改为 unsigned char a; 就会正常。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

686

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
10925
金钱
10925
注册时间
2014-6-12
在线时间
1042 小时
发表于 2019-3-22 16:06:02 | 显示全部楼层
你把 char a; 改为 unsigned  char a;  就会正常。
回复

使用道具 举报

头像被屏蔽

18

主题

184

帖子

0

精华

禁止发言

积分
258
金钱
258
注册时间
2019-1-10
在线时间
10 小时
发表于 2019-3-22 17:00:35 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

51

主题

2166

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10653
金钱
10653
注册时间
2017-4-14
在线时间
2780 小时
发表于 2019-3-22 17:22:24 | 显示全部楼层
①a=0xc0=1100 0000 >6  =0000 0011(高位补零)   & 0xff =0000 0011 =3
回复

使用道具 举报

8

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2019-1-18
在线时间
18 小时
 楼主| 发表于 2019-3-23 08:28:04 来自手机 | 显示全部楼层
nashui_sx 发表于 2019-3-22 17:22
①a=0xc0=1100 0000 >6  =0000 0011(高位补零)   & 0xff =0000 0011 =3

可是a我是声明的char  在右移时候不是应该要扩展符号位所以为 1111 1111才对么?

如果像你说的这样的按unsigned char右移,那为何当后边的&0xff 修改成0xfe 时整个运算的结果又成了0xfe了?
有哪里理解错误吗,还请解答,谢谢
回复

使用道具 举报

8

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2019-1-18
在线时间
18 小时
 楼主| 发表于 2019-3-23 08:29:41 来自手机 | 显示全部楼层
xuyaqi 发表于 2019-3-22 16:06
你把 char a; 改为 unsigned  char a;  就会正常。

就是声明成char,然后这两种情况的原因想探究下
回复

使用道具 举报

2

主题

686

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
10925
金钱
10925
注册时间
2014-6-12
在线时间
1042 小时
发表于 2019-3-23 10:11:54 | 显示全部楼层
本帖最后由 xuyaqi 于 2019-3-23 10:17 编辑
huangtaichen 发表于 2019-3-23 08:29
就是声明成char,然后这两种情况的原因想探究下

转载:
char类型数据向右移位时符号位问题
首先运行环境是51单片机+KEIL C
最近写一个16进制数据转换成ASCII形式的函数,多次运行发现,当16进制数据高4位大于8时,转换就出错。
最开始出错的程序如下:
void hex2ascii(char hex, char ascii[])
{
        char i = 0;
         ascii[0] = (hex & 0xf0) >> 4;
        ascii[1] = hex & 0x0f;
        sendNChar(ascii, 2);
        for (i=0; i<=1; i++)
        {
                if (ascii >= 0xa)
                {
                        ascii = ascii - 0xa + 'A';
                }
                else
                {
                        ascii = ascii + '0';
                }
        }
         sendNChar(ascii, 2);
}
在KEIL C51环境下,输入0xe3,输出fe 03 2e 33。
在VC环境下,输出输入0xe3,输出e 3 45 33
后来多次修改尝试,并分析原因。终于发现原因:hex是char类型,是有符号型,移位左边补符号位1。
故得fe,ascii[0]=0xfe是负数,小于0xa,故结果=0xfe+'0'=0x2e(溢出后结果)。
但不对,VC上运行正常呀,再分析
在VC上,int型占32位
按照C语言的自动类型转换原理
hex & 0xf0,分别是char和const int类型,转换成int型0xffffffe3 & 0x000000f0 = 0x000000e0
看来是,VC上运算移位时左边填充0,KEIL C51上运算移位时左边填充的是1.
        int debug = 0;
        debug = hex & 0xf0;
        sendNChar(&debug, 2);
KEIL C51下输出ff e0
VC下输出e0
找到这里知道程序错误的起因了,但hex & 0xf0处理的原因还不了解。
先断续调我的51程序。
这种地方 以后都要用unsigned char类型了,免得不必要的麻烦!



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-24 05:10

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表