找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2450|回复: 15
打印 上一主题 下一主题
收起左侧

C语言经过位移运算把指针里面的值赋给变量为什么会在高八位上?

[复制链接]
回帖奖励 5 黑币 回复本帖可获得 5 黑币奖励! 每人限 1 次
跳转到指定楼层
楼主
ID:1043477 发表于 2022-10-13 11:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

程序如下,用的是51单片机
#include "RX8F103.h"
#include "intrins.h"
#include <stdio.h>

//从串口发送一个字符
void EUart0_SendOneChar(char c)
{
        ES0=0;                                //发送数据时关串口中断
        TI0=0;                                //清TI位
        S0BUF = c;                //将待发送字符放入串口数据缓冲寄存器,并开始传输。
        while(!TI0);        //等待传送结束。当字符发送结束后由硬件置位请求中断,
                                                                //此时while循环结束,而串口中断处理函数需等到ES重新置1后才可能响应。
        TI0=0;                                //软件清TI位,亦可在中断处理函数中清0
        ES0 = 1;                        //开串口中断
}

void EUart0_SendString(char *st)
{
        while(*st)
        {
                EUart0_SendOneChar(*st++);
        }
}

unsigned char x[50] ={0x1e,0x00,0x00,0x00,0xca,0xfb,0x5f,0xf8,0x8f,0x00,0x1a,0x00,0x02,0xcf,0x81,
                      0xdb,0xff,0xe7,0xc8,0x00,0x20,0x00,0x01,0x5e,0x46,0xf5,0x71,0xd1,0x50,0x00,
                      0x21,0x00,0x01,0xa9,0xe1,0xfc,0xdf,0xc0,0x85,0x00,0x23,0x00,0x02,0xc8,0x44,
                      0xd7,0xf5,0xe9,0x47,0x00};


void main(void)
{        int a1=8;
        int a2=0x8f;
        int a3;

        unsigned char* iKeyP = x;
        CLKCON |= 0x1F;                                //默认所有时钟打开
        RSTPORTEN = 1;                                //使能复位功能

        UART0PORTEN = 1;                        //串口端口使能
        S0CON = 0x50;                                        //SCON: Mode 1, 8-bit UART, Enable Rcvr
        S0RELH = 0x03;                                //S0RELH + S0RELL  构成波特率设置S0REL[9:0]
        S0RELL = 0xF7;                                //Baud rate  = SYSCK/(16×(1024-S0REL))  SYSCK跟CLKDIV寄存器有关  波特率为115200
        ES0 = 1;                                                        //允许串口中断位
        EUart0_SendString("RX8F103 IIC Slave Init! V2.0\r\n");
        a1 = ((long)(a1)) << (9);
        a2 = (a2)+(128);
        a3 = *((short*)(iKeyP + (8)));
  while(1)
        {
                printf("Hello RX8F103 UART0\r\n");
                printf("a1==0x%x\r\n",a1);
                printf("a2==0x%x\r\n",a2);
                printf("a3==0x%x\r\n",a3);
        }
}

char putchar (char c)
{
        EUart0_SendOneChar(c);
        return c;
}

以下位打印的结果
RX8F103 IIC Slave Init! V2.0
Hello RX8F103 UART0
a1==0x1000
a2==0x10f
a3==0x8f00
问题在打印a3,a3不应该是a3=0x8f么,而是a3=0x8f00

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:526108 发表于 2022-10-13 12:49 | 只看该作者
a3 = *((char*)(iKeyP + (8)));
这样才是8F
回复

使用道具 举报

板凳
ID:883242 发表于 2022-10-13 13:36 | 只看该作者
qq624353765 发表于 2022-10-13 12:49
a3 = *((char*)(iKeyP + (8)));
这样才是8F

我没有c51,但是按说有符号数会扩展符号吧?8位的0x8f扩展成16位会当成负数扩展成0xff8f。
回复

使用道具 举报

地板
ID:844772 发表于 2022-10-13 15:09 | 只看该作者
没啥不对的啊,你强制类转换char型指针为short型,short每次走两个字节,于是读出来的是:0x8f,0x00两个数,不就是0x8f00
回复

使用道具 举报

5#
ID:883242 发表于 2022-10-13 18:27 | 只看该作者
glinfei 发表于 2022-10-13 15:09
没啥不对的啊,你强制类转换char型指针为short型,short每次走两个字节,于是读出来的是:0x8f,0x00两个数 ...

大端是0x8f00,小端是0x8f。

8位机本身根本就没有大小端问题,但是高级语言编译器有超过1字节的数据类型,那么必然就有大小端问题,取决于具体的编译器。对于8051来说,Keil C51是大端,IAR8051和SDCC是小端。
回复

使用道具 举报

6#
ID:384109 发表于 2022-10-13 20:48 | 只看该作者
这个好像是数据在内存存储方式和C语言缺省排序的问题
回复

使用道具 举报

7#
ID:844772 发表于 2022-10-14 09:15 | 只看该作者
Hephaestus 发表于 2022-10-13 18:27
大端是0x8f00,小端是0x8f。

8位机本身根本就没有大小端问题,但是高级语言编译器有超过1字节的数据类 ...

这不是大小端问题,是偏巧下一个数字是0,它强制类转换成short,一次提取了两个字节,合并成一个数。如果加7,也就是 a3 = *((short*)(iKeyP + (7))); 那结果就是0xf88f
回复

使用道具 举报

8#
ID:883242 发表于 2022-10-14 12:07 | 只看该作者
glinfei 发表于 2022-10-14 09:15
这不是大小端问题,是偏巧下一个数字是0,它强制类转换成short,一次提取了两个字节,合并成一个数。如果 ...

short是两个字节,在内存里面必然有字节序问题,到底是高位在前(小地址)还是低位在前总要有个约定。

16位机、32位机有多字节指令,字节序由指令确定,你可以违反字节序,代价就是代码长度和运行时间的恶化。以Cortex-M为例,ARM卖出的内核是可以配置成大端或者小端模式,有一个标志位,芯片厂家生产的时候写死,一旦生产出来大端还是小端已经确定了,目前已知所有Cortex-M单片机都是小端模式。那么根据你的说法,下一数字偏巧是0,根据小端模式高字节在低地址的定义,提取出来的short就是0x008f。

这就叫大端和小端!
回复

使用道具 举报

9#
ID:384109 发表于 2022-10-14 12:33 | 只看该作者
的确是大小端的问题,简单的说就是多字节数据在存储时地址方向的问题,就是存储地址是增加方向,还是减少方向的问题,不同的芯片会有不同的
回复

使用道具 举报

10#
ID:883242 发表于 2022-10-17 23:20 | 只看该作者
人中狼 发表于 2022-10-14 12:33
的确是大小端的问题,简单的说就是多字节数据在存储时地址方向的问题,就是存储地址是增加方向,还是减少方 ...

8位机哪来的什么大小端问题?但是编译器有多字节数据就有大小端问题。至少在8051这个平台上,大小端问题跟芯片无关,只跟编译器有关。
回复

使用道具 举报

11#
ID:1048116 发表于 2022-10-18 09:17 | 只看该作者
51单片机字节存贮是大端模式
回复

使用道具 举报

12#
ID:883242 发表于 2022-10-18 10:23 | 只看该作者
QW192026 发表于 2022-10-18 09:17
51单片机字节存贮是大端模式

我在5楼的发言——

8位机本身根本就没有大小端问题,但是高级语言编译器有超过1字节的数据类型,那么必然就有大小端问题,取决于具体的编译器。对于8051来说,Keil C51是大端,IAR8051和SDCC是小端。

井底蛤蟆的天空可能只有碗口那么大。
回复

使用道具 举报

13#
ID:528966 发表于 2022-10-18 16:58 | 只看该作者
qq624353765 发表于 2022-10-13 12:49
a3 = *((char*)(iKeyP + (8)));
这样才是8F

这是正解
回复

使用道具 举报

14#
ID:883242 发表于 2022-10-22 20:01 | 只看该作者

16位数据截断成了8位数据,根本不符合要求,怎么就成了“正解”?
回复

使用道具 举报

15#
ID:915005 发表于 2022-10-24 13:53 | 只看该作者
glinfei 发表于 2022-10-13 15:09
没啥不对的啊,你强制类转换char型指针为short型,short每次走两个字节,于是读出来的是:0x8f,0x00两个数 ...

4楼说得很对 不是 在高八位上 而是 按照short 类型 根据 你给的+8偏移量开始 在数组中取了两个字节 形成了0x8f00
回复

使用道具 举报

16#
ID:915005 发表于 2022-10-24 14:03 | 只看该作者
问题的根源 应该还是在各平台对数据类型的定义的差异上 语言 编译器和硬件的相关文档 要拿出来对照
回复

使用道具 举报

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

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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