該程序不會更改該陣列的「基地址」。它甚至沒有嘗試。
你傳遞給fn的是內存中256個字符塊的地址。它在數字上與str
在其他表達式中衰減的指針相同,只是不同的類型。在這裏,數組真的保持一個數組 - 將地址運算符應用到數組是數組不會衰減到指針的一個實例。例如,增量&str
會使其數值增加256.這對於多維數組非常重要,正如我們所知,它實際上是C中的一維數組陣列。增加「二維」數組的第一個索引必須將地址提前到下一個「塊」或「行」的開始處。
現在趕上。就fn而言,您通過的地址指向包含另一地址的位置。那是不正確的;它指向一系列字符。打印該字節序列解釋爲指針會顯示'A'字節值,即65或0x41。然而,fn認爲指向的內存包含一個地址,並用「kj」駐留在內存中的地址覆蓋它。由於在str中分配了足夠的內存來保存地址,因此分配成功並在該位置生成可用地址。
應該指出,這當然不能保證工作。導致失敗的最常見原因應該是對齊問題 - 我認爲str
不需要爲指針值正確對齊。標準規定函數參數必須與參數聲明兼容。任意指針類型不能分配給對方(需要通過void指針或者強制轉換)。
編輯: david.pfx指出(即使有適當的轉換),代碼調用未定義的行爲。該標準要求通過最新公共草案第6.5/7節中兼容的左值(包括引用的指針)來訪問對象。當正確編譯和編譯gcc -fstrict-aliasing -Wstrict-aliasing=2 ...
gcc警告「類型雙關」。理由是編譯器應該自由地假設不兼容的指針不會修改相同的內存區域;這裏不需要假定fn改變str的內容。這使得編譯器能夠優化不必要的重新加載(例如從內存到註冊)。這將對優化起作用;一個調試會話將無法重現錯誤的可能示例(即,如果正在調試的程序將被編譯而不進行用於調試目的的優化)。話雖如此,如果一個非優化編譯器會在這裏產生意想不到的結果,我會感到驚訝,所以我讓剩下的答案保持原樣。 -
我插入了一些debug printfs來說明發生了什麼。現場可以看到一個實例:http://ideone.com/aL407L。
#include<stdio.h>
#include<string.h>
static char* abc = "kj";
// Helper function to print the first bytes a char pointer points to
void printBytes(const char *const caption, const char *const ptr)
{
int i=0;
printf("%s: {", caption);
for(i=0; i<sizeof(char *)-1; ++i)
{
printf("0x%x,", ptr[i]);
}
printf("0x%x ...}\n", ptr[sizeof(char *)-1]);
}
// What exactly does this function do?
void fn(char**s) {
printf("Inside fn: Argument value is %p\n", s);
printBytes("Inside fn: Bytes at address above are", (char *)s);
// This throws. *s is not a valid address.
// printf("contents: ->%s<-\n", *s);
*s = abc;
printf("Inside fn: Bytes at address above after assignment\n");
printBytes(" (should be address of \"kj\")", (char *)s);
// Now *s holds a valid address (that of "kj").
printf("Inside fn: Printing *s as string (should be kj): ->%s<-\n", *s);
}
int main() {
char str[256];
printf("size of ptr: %zu\n", sizeof(void *));
strcpy(str, "AAAAAAAA"); // 9 defined bytes
printf("addr of \"kj\": %p\n", abc);
printf("str addr: %p (%p)\n", &str, str);
printBytes("str contents before fn", str);
printf("------------------------------\n");
// Paramter type does not match! Illegal code
// (6.5.16.1 of the latest public draft; incompatible
// types for assignment).
fn(&str);
printf("------------------------------\n");
printBytes("str contents after fn (i.e. abc -- note byte order!): ", str);
printf("str addr after fn -- still the same! --: %p (%p)\n", &str, str);
return 0;
}
爲後人,[這裏](http://stackoverflow.com/questions/25660493/assigning-to-a-char-array-using-assignment-operator-and-double-pointers)是刪除的問題 – 2014-09-04 11:34:36