Re: [問題] 指標與字元轉換問題
※ 引述《netsky (芒果冰)》之銘言:
恕刪。
: printf("%d",c);
我覺得這行有問題,應該是做 *c 才有問的價值。
為引述此問題,我想先跳個 tone , 看另一個程式碼做為引述 ,
沒興趣的話直接拉到 貮、 原問題 去看解答說明就好。
聲明的是 , 下面程式碼目前在少數場合還是看得到 ,
都還算是符合標準。
----
壹、 pointer hack
unsigned i, x=0x12345678;
char *p=(char*)&x;
for(i=0; i!=sizeof(x); ++i)
printf("address(%08x) : %02hhx", &p[i], p[i]);
在環境為 little endian , 執行出來的結果如下
address(0012ff54) : 78
address(0012ff55) : 56
address(0012ff56) : 34
address(0012ff57) : 12
在記憶體裡面長這樣
x頭
Var. x0 x1 x2 x3
┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
Addr │0x54│0x55│0x56│0x57│ │ │ │ │ │ │ │
┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
Value │0x78│0x56│0x34│0x12│ │ │ │ │ │ │ │
└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴
然而在解釋 unsigned x 的時候,它是從 x0 開始,往後抓了 4 bytes 到 x3,
且注意到 , 它的順序,一開始高位元部份,是存在較底位部份,
for 4bytes,
(1) 抓 x0, 放在最低1bytes , 0x ?? ?? ?? 78
(2) 抓 x1, 放在次低1bytes , 0x ?? ?? 56 78
(3) 抓 x2, 放在次高1bytes , 0x ?? 34 56 78
(4) 抓 x3, 放在最高1bytes , 0x 12 34 56 78
這是 little endian 特性。 於是才會顯示出 0x12345678。
意思是如果今天再多弄一個 unsigned short* 出來的話,
unsigned i, x=0x12345678;
unsigned short *p=(unsigned short *)&x;
for(i=0; i!=sizeof(x)/sizeof(unsigned short); ++i)
printf("address(%08x) : %04hx\n", &p[i], p[i]);
在 p[0] 時,會從開頭位置 x0,抓取 unsigned short (2bytes) 大小之資料,
從上面原則,於是從 x0 開始抓 2 bytes, 得到 0x5678,
而 p[1] 時,會從開頭位置 x2,抓取 unsigned short (2bytes) 大小之資料,
為何是從 x2 開始?簡單的說,因為 p 指向 unsigned short 2bytes,
所以 p[1] = address start of p + 1 * sizeof(unsigned short);
在實際上,記憶體之位置長這樣
|<-0*short->|<-1*short->|
p[0] p[1]
Var. x0 x1 x2 x3
┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
Addr │0x54│0x55│0x56│0x57│ │ │ │ │ │ │ │
┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
Value │0x78│0x56│0x34│0x12│ │ │ │ │ │ │ │
└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴
注意到 p[0] 是對到 x0, p[1] 是對到 x2 , 故 p[1] 取出為 0x1234。
比較有得講的是 p[1]。事實上,compiler 在計算 p[0]、p[1] 位置時,
有一個重要的參考依據,就是 pointer 指向的資料型態,
假設為 Type* pointer ,而 pointer[i] ,取到的位置是
pointer[i] 位置 = pointer 開頭位置 + Type大小 * i,
因 pointer 現在是 unsigned short, 於是
pointer[1] 位置 = 0x54 + sizeof(unsigned short)*1 = 0x56
這裡和 array 計算位置方式沒什麼兩樣,但重點是「翻譯」的地方,
在 little endian 的部份,data type 使用 byte 數確定後,是從後面翻回來的。
----
貮、 原問題
再把上面最重要的結論說一次
在 little endian 的部份,data type 使用 byte 數確定後,是從後面翻回來的。
回到原問題,將 code 改如下所述
char a[6]={0,1,2,3,4,5};
char *b;
int *c;
b=a;
b+=2;
c=(int*)b;
printf("*c = %d (%08x)\n", *c, *c);
現在一行一行看
※ char a[6] = {0,1,2,3,4,5};
Var. a0(a) a1 a2 a3 a4 a5
┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
Addr │0x58│0x59│0x5a│0x5b│0x5c│0x5d│ │ │ │ │ │
┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
Value │0x00│0x01│0x02│0x03│0x04│0x05│ │ │ │ │ │
└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴
※ b=a;
b
Var. a0(a) a1 a2 a3 a4 a5
┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
Addr │0x58│0x59│0x5a│0x5b│0x5c│0x5d│ │ │ │ │ │
┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
Value │0x00│0x01│0x02│0x03│0x04│0x05│ │ │ │ │ │
└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴
※ b+=2;
b
Var. a0(a) a1 a2 a3 a4 a5
┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
Addr │0x58│0x59│0x5a│0x5b│0x5c│0x5d│ │ │ │ │ │
┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
Value │0x00│0x01│0x02│0x03│0x04│0x05│ │ │ │ │ │
└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴
※ c=(int*)b;
b, c
Var. a0(a) a1 a2 a3 a4 a5
┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
Addr │0x58│0x59│0x5a│0x5b│0x5c│0x5d│ │ │ │ │ │
┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
Value │0x00│0x01│0x02│0x03│0x04│0x05│ │ │ │ │ │
└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴
接著確定 c 的資料範圍,4 bytes
|<------- c ---------->|
Var. a0(a) a1 a2 a3 a4 a5
┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
Addr │0x58│0x59│0x5a│0x5b│0x5c│0x5d│ │ │ │ │ │
┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
Value │0x00│0x01│0x02│0x03│0x04│0x05│ │ │ │ │ │
└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴
最後再從後面翻回來, 得到 *c = 0x05040302,這就是答案。
而 address of (*c) , 本身就和 a[2] 一樣,沒什麼好討論,
故認為原 po 應是筆誤寫錯。
----
有興趣看一下進階題
unsigned char a[]={
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
};
unsigned char *b=a+3;
unsigned int *c=(unsigned int*)b;
c+=2;
printf("*c=%08x\n", *c);
上面兩點看懂的話,這個也沒問題了,更難一點的考題是,
用 float* 去接,最後問 %.15e , *c 值是多少, 這應該會死更多人。
以上若有誤或其他意見,請指正 。
--
No matter how gifted you are,
alone, can not change the world.
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 180.177.78.41
推
10/13 01:26, , 1F
10/13 01:26, 1F
推
10/13 01:32, , 2F
10/13 01:32, 2F
推
10/13 02:23, , 3F
10/13 02:23, 3F
→
10/13 02:23, , 4F
10/13 02:23, 4F
→
10/13 02:27, , 5F
10/13 02:27, 5F
→
10/13 02:28, , 6F
10/13 02:28, 6F
※ 編輯: tropical72 來自: 180.177.78.41 (10/13 02:45)
推
10/13 10:47, , 7F
10/13 10:47, 7F
→
10/13 11:46, , 8F
10/13 11:46, 8F
推
10/13 11:56, , 9F
10/13 11:56, 9F
→
10/13 11:58, , 10F
10/13 11:58, 10F
→
10/13 11:59, , 11F
10/13 11:59, 11F
推
10/13 20:20, , 12F
10/13 20:20, 12F
→
10/13 20:21, , 13F
10/13 20:21, 13F
→
10/13 20:21, , 14F
10/13 20:21, 14F
→
10/13 20:48, , 15F
10/13 20:48, 15F
→
10/13 21:12, , 16F
10/13 21:12, 16F
→
10/13 21:12, , 17F
10/13 21:12, 17F
→
10/13 21:13, , 18F
10/13 21:13, 18F
推
10/13 21:13, , 19F
10/13 21:13, 19F
→
10/13 21:14, , 20F
10/13 21:14, 20F
→
10/13 23:15, , 21F
10/13 23:15, 21F
→
10/13 23:16, , 22F
10/13 23:16, 22F
討論串 (同標題文章)