[英]Confusion about static and dynamic arrays in C
typedef struct mystruct{
int a;
char arr[10];
char *str;
}mystruct;
void f(void *data, int offset){
char *s = (char *)(data + offset);
printf("%s", s);
}
void g(void *data, int offset){
char *s = *(char **)(data+offset);
printf("%s", s);
}
int main(){
mystruct test;
test.a = 2;
test.str = malloc(100);
strcpy(test.arr, "Hello ");
strcpy(test.str, "World!");
f(&test, offsetof(mystruct,arr));
g(&test, offsetof(mystruct,str));
return 0;
}
我想知道為什么我需要兩種不同的方式來打印字符串。 在函數f中 ,實際指向的是什么(數據+偏移量)? 是不是指向arr哪個是指向字符串第一個元素的char指針? 但是在函數g中 ,(data + offset)也指向了char指針。 那么為什么必須使用兩種不同的方法來完成同樣的任務呢?
在這兩種情況下, data+offset
指向結構的成員 。
但是讓我們看看結構的結構。 它包括
+-----+--------------------------------------------+
| a | sizeof(int) probably 4 or 8 bytes |
+-----+--------------------------------------------+
| possible padding of unknown size (probably zero) |
+-----+--------------------------------------------+
| arr | 10 bytes |
+-----+--------------------------------------------+
| possible padding of unknown size (maybe 2 bytes) |
+-----+--------------------------------------------+
| str | sizeof(char*) probably 4 or 8 bytes |
+-----+--------------------------------------------+
內存中的其他地方是用malloc
分配的100字節塊。
請注意,對於數據test.arr
存儲在分配內存test
,而是存儲在事test
對於test.str
是另一個內存塊的地址。
你必須給編譯器提供有關函數f
和g
中指針類型的信息,你不能對void指針進行點運算。
將data
轉換為char指針,printf將起作用
void f(void *data, int offset){
char *s = (char *)(( char*)data + offset);
printf("%s", s);
}
void g(void *data, int offset){
char *s = *(char **)((char*)data+offset);
printf("%s", s);
}
在函數
f
,實際指向的是什么(data + offset)
? 是不是指向arr
哪個是指向字符串第一個元素的char指針?
這是您混淆的主要原因。 arr
不是指針,它是一個數組。 數組不是指針。 同時, str
是一個指針。 “數組”和“指針”是兩個完全不同的東西。 他們幾乎沒有任何共同之處。 這正是您必須以不同方式使用它們的原因。
在所謂的值上下文中 (即當用作rvalues時 ),數組和指針的行為非常相似,但這純粹是膚淺的相似性。 他們立即揭示了他們在所謂的對象上下文中的主要差異(即當用作左值時 )。 在您的特定示例中,您的成員訪問代碼是對象上下文的示例,這就是您必須仔細觀察arr
和str
之間差異的原因。
數組和指針之間的差異問題已經涵蓋了很多次。 我認為沒有理由在此重復。 只需在SO上搜索“數組指針差異”即可。 或者閱讀必要的FAQ
http://c-faq.com/aryptr/index.html
PS還要注意C語言不支持void *
指針上的指針算法。 您的所有(data + offset)
表達式都無效。 你想要做的是((char *) data + offset)
。 為了能夠使用字節偏移執行點算術,需要將data
從void *
轉換為char *
。
在你的結構中,在(推測)偏移4處,是一個一個接一個的10個字節的列表,包含制作'Hello'的字母; 所以(data + 4)是char的指針,需要相應地進行dcoded(即char *
)。
然而,在那10個字節之后,來一些字節使緩沖區的地址在某處,即那些字節是'char *'(你定義它們),所以數據+偏移有一個指針在char指針或一個char **
。
可能令人困惑的是兩者兼而有之
strcpy(test.arr,“你好”);
strcpy(test.str,“World!”);
工作。
這是一個令人困惑的(但很有用的C / C ++特性)。 當數組的名稱在需要指向數組元素類型的指針的位置中使用時,編譯器將對其進行處理,就像它是指向數組的第一個元素的指針一樣。
所以test.str
顯然是一個指向char的指針(因為你這樣定義)。 如果情況表明, test.arr
可以用作指向第一個測試元素的指針。
當你寫strcpy(test.arr, "Hello ");
編譯器假設你的意思是strcpy(&test.arr[0], "Hello ");
在函數f中,實際指向的是什么(數據+偏移量)?
它指向結構對象的'arr'成員(如果你假設GCC的void指針算術的語義)。
是不是指向arr哪個是指向字符串第一個元素的char指針?
arr是一個char數組,而不是char指針。
但是在函數g中,(data + offset)也指向了char指針。
在這種情況下,它指向一個char指針,是的。
那么為什么必須使用兩種不同的方法來完成同樣的任務呢?
指針指向兩個不同的東西 - 一個指向char指針(它本身指向一個char數組),另一個指向char數組。 在第一種情況下還有一個間接級別。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.