當運行此代碼:指針在C,整數指針字符指針
int arr[3] = {2,3,4};
char *p;
p = (char*)arr;
printf("%d", *p);
p = p+1;
printf("%d", *p);
輸出是2和0。第二個結果是稍微混亂。有人可以解釋爲什麼發生這種情況?
當運行此代碼:指針在C,整數指針字符指針
int arr[3] = {2,3,4};
char *p;
p = (char*)arr;
printf("%d", *p);
p = p+1;
printf("%d", *p);
輸出是2和0。第二個結果是稍微混亂。有人可以解釋爲什麼發生這種情況?
讓我們打破這:
int arr[3] = {2,3,4};
創建的3個整數的數組。假設你的系統是32位小尾數,這是它的外觀在內存:
02 00 00 00 03 00 00 00 04 00 00 00
char *p; p = (char*)arr;
p
現在指向arr
但它是一個指針char*
。換句話說,p
指向02
。
printf("%d", *p);
您打印爲int
由p
引用的位置。所以,當你提領p
(寫*p
)您正在訪問的char
(因爲p
是類型char*
的)由p
引用。這是02
。
p = p+1;
p
現在指向00
剛02
後,因爲p
是char*
。所以當你加1時,它會在內存中移動1 * sizeof(char) = 1 * 1 = 1
字節。
printf("%d", *p);
您打印爲int
由p
引用的位置。因此,當您使用取消引用p
(通過書寫*p
)您正在訪問p
引用的char
(因爲p
的類型爲char*
)。這是00
。
如果你想打印3
而不是0
你有你的指針類型更改爲int*
而不是char*
,通過在內存1 * sizeof(int) = 1 * 4 = 4
字節使指針移動。
非常感謝!!! :-) – user1124236 2011-12-31 11:28:05
我還要強調,當讀取'int'類型的值時,就好像它們是'char是合法的,確切的結果取決於實施。在別處編譯時可能會得到另一個結果。 @Cicada必須對平臺做出假設才能提供答案。 – Kos 2011-12-31 11:30:43
假設int是32位,如果平臺是32位或64位(甚至16位),則無關緊要。在一個翻轉的筆記上,對endianness的思考對我來說發生得非常晚,我曾經假設只存在小端類型。來自6502,z80和8088,令人驚訝的是這些數字可以用不同的方式表示。 – bestsss 2011-12-31 17:20:19
你得到的結果將取決於你的實現和它的字節順序的大小int
。
假設32位整型,8位字符和豆蔻端環境(比如86),arr
會是這樣的記憶:
<arr[0]> <arr[1]> <arr[2]>
02 00 00 00 03 00 00 00 04 00 00 00
^^ ^
p p+1 ... p+4
如果你把一個字符指針到內存的開始,打印出第一個元素,應輸出2
。如果增加該指針,則會輸出0。您需要將其增加幾次以「看」3.
請注意,在具有相同類型大小的大端環境中,您的程序將輸出兩個零,因爲佈局可能是:
<arr[0]> <arr[1]> <arr[2]>
00 00 00 02 00 00 00 03 00 00 00 04
^^ ^
p p+1 ... p+4
這裏是一個貼,可以讓你瞭解這個問題更好:http://codepad.org/ClrrwjKY
正如你所看到的,連續整數的值出現三個零分開。這是因爲一個整數是4個字節長,而一個char只有1個字節長。因此,當int數組轉換爲char時,可以逐字節(或char by char)而不是四個字節(int by int)迭代它。
這是因爲所謂的endianness。
當你創建了int arr[3] = {2, 3, 4};
它就會在內存中創建一個數組如下
Big endian:
0 1 2 3 4 5 6 7 8 9 10 11
+---+---+---+--------+---+---+---+--------+---+---+---+--------+
| | | | ..0010 | | | | ..0011 | | | | ..0100 |
+---+---+---+--------+---+---+---+--------+---+---+---+--------+
<-- 2 --><-- 3 --><-- 4 -->
Little endian:
0 1 2 3 4 5 6 7 8 9 10 11
+--------+---+---+---+---------+---+---+---+--------+---+---+---+
| ..0010 | | | | ..0011 | | | | ..0100 | | | |
+--------+---+---+---+---------+---+---+---+--------+---+---+---+
<-- 2 --><-- 3 --><-- 4 -->
要了解更多,你需要修改你的程序如下:
int main(void)
{
int arr[3] = {2, 3, 4};
char *p = (char*) arr;
int i;
int size = (int)sizeof(arr);
for (i=0; i<size ; i++) {
printf("%d", *p);
p++;
}
return 0;
}
而且,檢查您硬件的字節順序,您可以使用以下功能。僅由1 作爲陣列
void endian(void)
{
int i = 1;
if (*(char *) &i == 1)
printf("Little endian \n");
else
printf("Big endian \n");
return;
}
這裏爲「p」爲一個字符指針.. P + 1倍的增量p的電流值是整數,以便通過一個訪問數組一個的每個值,就必須通過2. 遞增字符數組如果整數數組的地址因此1000 ,
arr[0] is at 1000
arr[1] is at 1002
arr[2] is at 1004
和改編的值是ARR [0]的地址; 所以最初
p=arr=1000
當p遞增,p是1001而ARR [1]是1002
..所以爲了訪問所有的值你就必須增加p的值的兩倍每次..
這是功課嗎?如果是這樣 - 相應地標記它。 – littleadv 2011-12-31 11:08:28
當你*運行這段代碼時發生了什麼?推理:在發佈問題之前,向我們展示您嘗試過的內容以及結果是個好主意。 – 2011-12-31 11:11:10
輸出是2和0.第二個結果有點混亂。因此,這個問題。我是一位心臟外科醫生,他正在努力幫助我的兒子完成作業。不幸的是,上帝並沒有讓我們所有人都成爲C專家。 – user1124236 2011-12-31 11:12:57