標(biāo)題: C語(yǔ)言經(jīng)過(guò)位移運(yùn)算把指針里面的值賦給變量為什么會(huì)在高八位上? [打印本頁(yè)]

作者: yxyxyxyx    時(shí)間: 2022-10-13 11:18
標(biāo)題: C語(yǔ)言經(jīng)過(guò)位移運(yùn)算把指針里面的值賦給變量為什么會(huì)在高八位上?

程序如下,用的是51單片機(jī)
#include "RX8F103.h"
#include "intrins.h"
#include <stdio.h>

//從串口發(fā)送一個(gè)字符
void EUart0_SendOneChar(char c)
{
        ES0=0;                                //發(fā)送數(shù)據(jù)時(shí)關(guān)串口中斷
        TI0=0;                                //清TI位
        S0BUF = c;                //將待發(fā)送字符放入串口數(shù)據(jù)緩沖寄存器,并開始傳輸。
        while(!TI0);        //等待傳送結(jié)束。當(dāng)字符發(fā)送結(jié)束后由硬件置位請(qǐng)求中斷,
                                                                //此時(shí)while循環(huán)結(jié)束,而串口中斷處理函數(shù)需等到ES重新置1后才可能響應(yīng)。
        TI0=0;                                //軟件清TI位,亦可在中斷處理函數(shù)中清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;                                //默認(rèn)所有時(shí)鐘打開
        RSTPORTEN = 1;                                //使能復(fù)位功能

        UART0PORTEN = 1;                        //串口端口使能
        S0CON = 0x50;                                        //SCON: Mode 1, 8-bit UART, Enable Rcvr
        S0RELH = 0x03;                                //S0RELH + S0RELL  構(gòu)成波特率設(shè)置S0REL[9:0]
        S0RELL = 0xF7;                                //Baud rate  = SYSCK/(16×(1024-S0REL))  SYSCK跟CLKDIV寄存器有關(guān)  波特率為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;
}

以下位打印的結(jié)果
RX8F103 IIC Slave Init! V2.0
Hello RX8F103 UART0
a1==0x1000
a2==0x10f
a3==0x8f00
問(wèn)題在打印a3,a3不應(yīng)該是a3=0x8f么,而是a3=0x8f00


作者: 624353765    時(shí)間: 2022-10-13 12:49
a3 = *((char*)(iKeyP + (8)));
這樣才是8F
作者: Hephaestus    時(shí)間: 2022-10-13 13:36
qq624353765 發(fā)表于 2022-10-13 12:49
a3 = *((char*)(iKeyP + (8)));
這樣才是8F

我沒(méi)有c51,但是按說(shuō)有符號(hào)數(shù)會(huì)擴(kuò)展符號(hào)吧?8位的0x8f擴(kuò)展成16位會(huì)當(dāng)成負(fù)數(shù)擴(kuò)展成0xff8f。
作者: glinfei    時(shí)間: 2022-10-13 15:09
沒(méi)啥不對(duì)的啊,你強(qiáng)制類轉(zhuǎn)換char型指針為short型,short每次走兩個(gè)字節(jié),于是讀出來(lái)的是:0x8f,0x00兩個(gè)數(shù),不就是0x8f00
作者: Hephaestus    時(shí)間: 2022-10-13 18:27
glinfei 發(fā)表于 2022-10-13 15:09
沒(méi)啥不對(duì)的啊,你強(qiáng)制類轉(zhuǎn)換char型指針為short型,short每次走兩個(gè)字節(jié),于是讀出來(lái)的是:0x8f,0x00兩個(gè)數(shù) ...

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

8位機(jī)本身根本就沒(méi)有大小端問(wèn)題,但是高級(jí)語(yǔ)言編譯器有超過(guò)1字節(jié)的數(shù)據(jù)類型,那么必然就有大小端問(wèn)題,取決于具體的編譯器。對(duì)于8051來(lái)說(shuō),Keil C51是大端,IAR8051和SDCC是小端。
作者: 人中狼    時(shí)間: 2022-10-13 20:48
這個(gè)好像是數(shù)據(jù)在內(nèi)存存儲(chǔ)方式和C語(yǔ)言缺省排序的問(wèn)題
作者: glinfei    時(shí)間: 2022-10-14 09:15
Hephaestus 發(fā)表于 2022-10-13 18:27
大端是0x8f00,小端是0x8f。

8位機(jī)本身根本就沒(méi)有大小端問(wèn)題,但是高級(jí)語(yǔ)言編譯器有超過(guò)1字節(jié)的數(shù)據(jù)類 ...

這不是大小端問(wèn)題,是偏巧下一個(gè)數(shù)字是0,它強(qiáng)制類轉(zhuǎn)換成short,一次提取了兩個(gè)字節(jié),合并成一個(gè)數(shù)。如果加7,也就是 a3 = *((short*)(iKeyP + (7))); 那結(jié)果就是0xf88f
作者: Hephaestus    時(shí)間: 2022-10-14 12:07
glinfei 發(fā)表于 2022-10-14 09:15
這不是大小端問(wèn)題,是偏巧下一個(gè)數(shù)字是0,它強(qiáng)制類轉(zhuǎn)換成short,一次提取了兩個(gè)字節(jié),合并成一個(gè)數(shù)。如果 ...

short是兩個(gè)字節(jié),在內(nèi)存里面必然有字節(jié)序問(wèn)題,到底是高位在前(小地址)還是低位在前總要有個(gè)約定。

16位機(jī)、32位機(jī)有多字節(jié)指令,字節(jié)序由指令確定,你可以違反字節(jié)序,代價(jià)就是代碼長(zhǎng)度和運(yùn)行時(shí)間的惡化。以Cortex-M為例,ARM賣出的內(nèi)核是可以配置成大端或者小端模式,有一個(gè)標(biāo)志位,芯片廠家生產(chǎn)的時(shí)候?qū)懰溃坏┥a(chǎn)出來(lái)大端還是小端已經(jīng)確定了,目前已知所有Cortex-M單片機(jī)都是小端模式。那么根據(jù)你的說(shuō)法,下一數(shù)字偏巧是0,根據(jù)小端模式高字節(jié)在低地址的定義,提取出來(lái)的short就是0x008f。

這就叫大端和小端!
作者: 人中狼    時(shí)間: 2022-10-14 12:33
的確是大小端的問(wèn)題,簡(jiǎn)單的說(shuō)就是多字節(jié)數(shù)據(jù)在存儲(chǔ)時(shí)地址方向的問(wèn)題,就是存儲(chǔ)地址是增加方向,還是減少方向的問(wèn)題,不同的芯片會(huì)有不同的
作者: Hephaestus    時(shí)間: 2022-10-17 23:20
人中狼 發(fā)表于 2022-10-14 12:33
的確是大小端的問(wèn)題,簡(jiǎn)單的說(shuō)就是多字節(jié)數(shù)據(jù)在存儲(chǔ)時(shí)地址方向的問(wèn)題,就是存儲(chǔ)地址是增加方向,還是減少方 ...

8位機(jī)哪來(lái)的什么大小端問(wèn)題?但是編譯器有多字節(jié)數(shù)據(jù)就有大小端問(wèn)題。至少在8051這個(gè)平臺(tái)上,大小端問(wèn)題跟芯片無(wú)關(guān),只跟編譯器有關(guān)。
作者: QW192026    時(shí)間: 2022-10-18 09:17
51單片機(jī)字節(jié)存貯是大端模式

作者: Hephaestus    時(shí)間: 2022-10-18 10:23
QW192026 發(fā)表于 2022-10-18 09:17
51單片機(jī)字節(jié)存貯是大端模式

我在5樓的發(fā)言——

8位機(jī)本身根本就沒(méi)有大小端問(wèn)題,但是高級(jí)語(yǔ)言編譯器有超過(guò)1字節(jié)的數(shù)據(jù)類型,那么必然就有大小端問(wèn)題,取決于具體的編譯器。對(duì)于8051來(lái)說(shuō),Keil C51是大端,IAR8051和SDCC是小端。

井底蛤蟆的天空可能只有碗口那么大。
作者: 耿曉峰    時(shí)間: 2022-10-18 16:58
qq624353765 發(fā)表于 2022-10-13 12:49
a3 = *((char*)(iKeyP + (8)));
這樣才是8F

這是正解
作者: Hephaestus    時(shí)間: 2022-10-22 20:01
耿曉峰 發(fā)表于 2022-10-18 16:58
這是正解

16位數(shù)據(jù)截?cái)喑闪?位數(shù)據(jù),根本不符合要求,怎么就成了“正解”?
作者: Sean_Shao    時(shí)間: 2022-10-24 13:53
glinfei 發(fā)表于 2022-10-13 15:09
沒(méi)啥不對(duì)的啊,你強(qiáng)制類轉(zhuǎn)換char型指針為short型,short每次走兩個(gè)字節(jié),于是讀出來(lái)的是:0x8f,0x00兩個(gè)數(shù) ...

4樓說(shuō)得很對(duì) 不是 在高八位上 而是 按照short 類型 根據(jù) 你給的+8偏移量開始 在數(shù)組中取了兩個(gè)字節(jié) 形成了0x8f00
作者: Sean_Shao    時(shí)間: 2022-10-24 14:03
問(wèn)題的根源 應(yīng)該還是在各平臺(tái)對(duì)數(shù)據(jù)類型的定義的差異上 語(yǔ)言 編譯器和硬件的相關(guān)文檔 要拿出來(lái)對(duì)照




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1