#include "stdio.h"
int main(void) {
int x = 10;
int* xPtr = &x;
printf("x = %d, address = %p\n", x, xPtr);
printf("xPtr to unsigned long = %d(dec) %x(hex)", (unsigned long)xPtr, (unsigned long)xPtr );
}
將 int* 的指標強制轉型為 unsigned long
指標型態之間強制轉換
#include "stdio.h"
int main(){
int i; //a counter that avoid exceed the memory
unsigned char *ptr; // 8 bits
short short_num = 32767; // 16 bits
int int_num = 2147483647; // 32 bits
long long long_long_num = 9223372036854775807; // 64 bits
printf("short_num = %d (0x%x), address = 0x%p \n", short_num, short_num, &short_num);
ptr = &short_num; //將 ptr 指向 short_num
printf("ptr 指向 short_num, ptr = %x, ptr + 1 = %x \n", ptr, ptr+1);
for(i = 0; i < sizeof(short_num); i++){
printf("address 0x%x = 0x%x \n", ptr+i,*(ptr + i)); //拆解成 8 bits , 8 bits
}
printf("\n");
printf("int_num = %d (0x%x), address = 0x%p \n", int_num, int_num, &int_num);
ptr = &int_num;
printf("ptr 指向 int_num, ptr = %x, ptr + 1 = %x \n", ptr, ptr+1);
for(i = 0; i < sizeof(int_num); i++){
printf("address 0x%x = 0x%x \n", ptr+i,*(ptr + i)); //拆解成 8 bits , 8 bits
}
printf("\n");
printf("long_long_num = %lld (0x%llx), address = 0x%p \n", long_long_num, long_long_num, &long_long_num);
ptr = &long_long_num;
printf("ptr 指向 long_long_num, ptr = %x, ptr + 1 = %x \n", ptr, ptr+1);
for(i = 0; i < sizeof(long_long_num); i++){
printf("address 0x%x = 0x%x \n", ptr+i,*(ptr + i)); //拆解成 8 bits , 8 bits
}
}
但在數據型態上我們又常常用到如 char (1byte) 、 short (2bytes) 、 int (4bytes) 、 long long (8bytes) 在電腦中又是如何存放的呢?
首先我們針對 short_num 來看,我們先宣告它的數值為 32767
以十六進制來表示十進制的 32767 為 0x7fff (也就是 short 型別可表示的最大正整數)
而 short_num 在電腦中所存放的記憶體位址為 0x0028FF36
那這個 0x0028FF36 就存放著 32767 (0x7fff) 的數值嗎? 事實上如我們前面所說,一個記憶體位址只能存放 1 byte 的資料,所以他必須用到 "兩個記憶體位址"
也就是他將 0x0028FF36 以及 0x0028FF37 這兩個 2bytes 合併起來,用來表示一個 2 bytes 的數據
第六行我們宣告一個指向 unsigned char* 的指標變數 ptr
我們思考一下,先前我們說過當我們宣告一個 *int door 指標變數時,表示其應該要用來存放一個 int 型態數據的位址(或說 door 將會指向一個 int 型別的變數)。
而在第六行宣告一個指標變數 ptr ,其指向一個 unsigned char 變數又是什麼意思?
事實上這樣宣告後,當我們使用 *(米字號) 做為 "(依位址)取值運算子" 時,它就只會取 1 byte 的資料長度。以此類推,若我們宣告另一個指標變數 ptr1 為 short* 時,使用取址運算子對一個數據進行取值,就會一次取到 2 bytes 的資料(文末補充資料有宣告為 short* 時的結果)。
在第十三行的地方我們將 ptr 直接指向 short_num ,如此一來他就會指到 0x0028FF36 ( short_num 的位址開頭)
我們在 16 ~ 18 行列印出 *ptr 以及 *( ptr + 1 )
得到分割後的數據
記憶體位址 0x0028FF36 = 0xff
記憶體位址 0x0028FF37 = 0x7f
下圖中的上圖(!?) 為一個 16 bits ( 2 bytes ) 的數據,每一格代表一個 bit 。
第 0 格的地方我們稱為最低位元(LSB)
第 15 格的地方我們稱為最高位元(MSB)
下圖中的下圖(!?)
這樣的數據分割方式稱為 little endian ( Intel 系統使用 )
另一種數據分割方式為 big endian ,其被應用的系統更為廣泛的
分割後的排列的順序與上述正好相反
由上圖可以看出
若有一個數據以十六進制表示為 0x7FFFFFFF (總共使用 4 bytes 長度),且從記憶體位址 0x0028ff36 開始擺放這個數據
則
little endian :
其數據分割的方式為 "從低位元擺上去" ,也就是從雞蛋中的小邊打破這個雞蛋
big endian :
其數據分割的方式為 "從高位元往下擺",也就是從雞蛋中的大邊打破這個雞蛋
結論 :
顯然我的電腦是使用 little endian (Intel 系統)
關於 big & little endian 有一個有趣的歷史小故事,可參考此連結
補充 :
#include "stdio.h"
int main(){
int i; //a counter that avoid exceed the memory
unsigned short *ptr; // 16 bits
printf("The address of pointer = %p \n\n", &ptr);
short short_num = 32767; // 16 bits
int int_num = 2147483647; // 32 bits
long long long_long_num = 9223372036854775807; // 64 bits
printf("short_num = %d (0x%x), address = 0x%p \n", short_num, short_num, &short_num);
ptr = &short_num; //將 ptr 指向 short_num
printf("ptr 指向 short_num, ptr = %x, ptr + 1 = %x \n", ptr, ptr+1);
for(i = 0; i < sizeof(short_num); i++){
printf("address 0x%x = 0x%x \n", ptr+i,*(ptr + i)); //拆解成 16 bits , 16 bits
}
printf("\n");
printf("int_num = %d (0x%x), address = 0x%p \n", int_num, int_num, &int_num);
ptr = &int_num;
printf("ptr 指向 int_num, ptr = %x, ptr + 1 = %x \n", ptr, ptr+1);
for(i = 0; i < sizeof(int_num); i++){
printf("address 0x%x = 0x%x \n", ptr+i,*(ptr + i)); //拆解成 16 bits , 16 bits
}
printf("\n");
printf("long_long_num = %lld (0x%llx), address = 0x%p \n", long_long_num, long_long_num, &long_long_num);
ptr = &long_long_num;
printf("ptr 指向 long_long_num, ptr = %x, ptr + 1 = %x \n", ptr, ptr+1);
for(i = 0; i < sizeof(long_long_num); i++){
printf("address 0x%x = 0x%x \n", ptr+i,*(ptr + i)); //拆解成 16 bits , 16 bits
}
}
#include "stdio.h"
int main(){
int i; //a counter that avoid exceed the memory
unsigned int *ptr; // 32 bits
printf("The address of pointer = %p \n\n", &ptr);
short short_num = 32767; // 16 bits
int int_num = 2147483647; // 32 bits
long long long_long_num = 9223372036854775807; // 64 bits
printf("short_num = %d (0x%x), address = 0x%p \n", short_num, short_num, &short_num);
ptr = &short_num; //將 ptr 指向 short_num
printf("ptr 指向 short_num, ptr = %x, ptr + 1 = %x \n", ptr, ptr+1);
for(i = 0; i < sizeof(short_num); i++){
printf("address 0x%x = 0x%x \n", ptr+i,*(ptr + i)); //拆解成 32 bits , 32 bits
}
printf("\n");
printf("int_num = %d (0x%x), address = 0x%p \n", int_num, int_num, &int_num);
ptr = &int_num;
printf("ptr 指向 int_num, ptr = %x, ptr + 1 = %x \n", ptr, ptr+1);
for(i = 0; i < sizeof(int_num); i++){
printf("address 0x%x = 0x%x \n", ptr+i,*(ptr + i)); //拆解成 32 bits , 32 bits
}
printf("\n");
printf("long_long_num = %lld (0x%llx), address = 0x%p \n", long_long_num, long_long_num, &long_long_num);
ptr = &long_long_num;
printf("ptr 指向 long_long_num, ptr = %x, ptr + 1 = %x \n", ptr, ptr+1);
for(i = 0; i < sizeof(long_long_num); i++){
printf("address 0x%x = 0x%x \n", ptr+i,*(ptr + i)); //拆解成 32 bits , 32 bits
}
}