我知道我們不允許在宣告指標時超出指標系結的記憶體位置寫入值。所以下面的代碼會編譯錯誤。
int a = 2, b = 3, c = 4;
int* d = &b;
*(d 1)=6; //ERROR
但是,為什么在這種情況下:
char str[] = "hello";
char* strB = &str[0];
*(strB 1) = 'E';
int i;
for (i = 0; i < 400; i ) {
printf("%c\n", *(strB i)); // hEllo followed by some trash value
}
將作業。里面沒有問題*(strB 1)=...嗎?指標strB最初指向一個char型別;但是,strB可以“看到”或“寫入”存盤在str[1]、 等中的值似乎是非法的str[2]。如果,當該區域已經被我們的程式擁有時,指標可以訪問其合法區域之外的區域,那么為什么第一個程式不起作用?我認為將的地址d 1對應于變數c或a居住的地方。
uj5u.com熱心網友回復:
我認為您只是對指標的作業方式有些困惑。希望我能為你解決問題。"*(strB 1) =..." 是合法的并且確實有意義。一個變數,以 int b = 3 為例,它有一個記憶體地址和一個這樣的值:(我編造了記憶體地址)
Variable Name Address Value
b 0x7ffc2ede6efc 3
現在,如果我們創建一個指向該變數的指標,那么該指標也將具有記憶體地址和值。在這里,我們宣告了一個名為“d”的整數型別的新指標變數,并希望將其值設定為變數 b的地址。
int* d = &b;
這是它在記憶體中的樣子。
Variable Name Address Value
d 0x8fcd2aff6ec4 0x7ffc2ede6efc
請注意,該值是上述變數“b”的記憶體地址。如果我們繼續列印指標“d”的值,它將列印一個記憶體地址。如果我們想實際列印該記憶體地址處的值,那么首先需要使用“*”取消參考它,這將列印指標值的值(如果有意義的話)。那么為什么第一部分是錯誤的是因為您之前在“d”的值上加了 1你取消參考它。所以你真的在改變“d”指向的記憶體地址,這可能是什么,也可能什么都不是。如果您先取消參考“d”,然后添加 1,您將能夠增加它,但要知道您實際上是在增加“b”。此外,如果您創建更多整數變數,并不意味著它們將在記憶體中一個接一個。列印我們的記憶體地址并親眼看看!
現在在第二種情況下,您正在處理字符陣列。陣列類似于指標。
char str[] = "hello";
char* strB = &str[0];
“str”值是陣列中第一個元素的地址。因此,您可以執行以下操作,而不是在陣列中的第一個元素上呼叫運算子的地址:
char* strB = str;
這也是字串在記憶體中的樣子:
Variable Name Address Value
str[0] 0x7ffc2ede6ef1 'h'
str[1] 0x7ffc2ede6ef2 'e'
str[2] 0x7ffc2ede6ef3 'l'
str[3] 0x7ffc2ede6ef4 'l'
str[4] 0x7ffc2ede6ef5 'o'
str[5] 0x7ffc2ede6ef6 '\0'
陣列中每個元素的地址彼此相鄰,這就是為什么您可以將 1 添加到 strB 并且它仍然有效。因為加 1 將移動到下一個地址,在這種情況下是陣列中的下一個字符。另一種列印方式可以是這樣的:
for (; *strB != '\0'; strB ) printf("%c", *strB);
每個字串都以空字符結尾,因此您可以從陣列的開頭開始,并通過向地址添加 1 來列印每個字符,直到到達空字符為止。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/314985.html
