簡體   English   中英

關於C中的靜態和動態數組的困惑

[英]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是另一個內存塊的地址。

你必須給編譯器提供有關函數fg中指針類型的信息,你不能對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時 ),數組和指針的行為非常相似,但這純粹是膚淺的相似性。 他們立即揭示了他們在所謂的對象上下文中的主要差異(即當用作左值時 )。 在您的特定示例中,您的成員訪問代碼是對象上下文的示例,這就是您必須仔細觀察arrstr之間差異的原因。

數組和指針之間的差異問題已經涵蓋了很多次。 我認為沒有理由在此重復。 只需在SO上搜索“數組指針差異”即可。 或者閱讀必要的FAQ

http://c-faq.com/aryptr/index.html

PS還要注意C語言不支持void *指針上的指針算法。 您的所有(data + offset)表達式都無效。 你想要做的是((char *) data + offset) 為了能夠使用字節偏移執行點算術,需要將datavoid *轉換為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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM