編輯:「大錯誤」部分更新。
C風格的快速教訓(從C++不同!)類型定義,以及爲什麼它是怎麼回事,以及如何使用它。
首先,一個基本的typedef把戲。
typedef int* int_pointer;
int_pointer ip1;
int *ip2;
int a; // Just a variable
ip1 = &a; // Sets the pointer to a
ip2 = &a; // Sets the pointer to a
*ip1 = 4; // Sets a to 4
*ip2 = 4; // Sets a to 4
IP1和IP2是相同的類型:一個指針到類型INT,即使你沒有把一個* IP1的聲明。這*代替了聲明。
切換主題。 你說話聲明數組作爲
int array1[4];
要做到這一點在運行時動態,你可以這樣做:
int *array2 = malloc(sizeof(int) * 4);
int a = 4;
array1[0] = a;
array2[0] = a; // The [] implicitly dereferences the pointer
現在,如果我們想要什麼指針數組?它看起來像這樣:
int *array1[4];
int a;
array1[0] = &a; // Sets array[0] to point to variable a
*array1[0] = 4; // Sets a to 4
讓我們動態地分配這個數組。
int **array2 = malloc(sizeof(int *) * 4);
array2[0] = &a; // [] implicitly dereferences
*array2[0] = 4; // Sets a to 4
注意int **。這意味着指針指向int。如果我們選擇,我們可以使用指針typedef。
typedef int* array_of_ints;
array_of_ints *array3 = malloc(sizeof(array_of_ints) * 4);
array3[0] = &a; // [] implicitly dereferences
*array3[0] = 4; // Sets a to 4
看看在最後的聲明中只有一個*嗎?這是因爲其中之一是「在typedef」。與去年的聲明,你現在有一個包含4個指向整數(INT *)大小爲4的數組。
這裏必須指出的運算符優先級是很重要的。解引用運算符[]優先於*之一。所以我們要做的就是:
*(array3[0]) = 4;
現在,讓我們將主題更改爲structs和typedefs。
struct foo { int a; }; // Declares a struct named foo
typedef struct { int a; } bar; // Typedefs an "ANONYMOUS STRUCTURE" referred to by 'bar'
爲什麼你會輸入一個匿名結構?那麼,爲了可讀性!
struct foo a; // Declares a variable a of type struct foo
bar b; // Notice how you don't have to put 'struct' first
聲明函數...
funca(struct foo* arg1, bar *arg2);
看看我們怎麼沒有把 '結構' 在arg2的前面?現在
,我們看到,你必須使用的代碼定義的結構以這種方式:
typedef struct { } * foo_pointers;
這類似於我們是怎麼做的指針之前的數組:
typedef int* array_of_ints;
比較並排
typedef struct { } * foo_pointers;
typedef int* array_of_ints;
唯一的區別是一個是struct {},另一個是int。
隨着我們foo_pointers,我們可以聲明數組的指針到foo這樣:
foo_pointers fooptrs[4];
現在我們有了一個數組,商店4個指向一個匿名的結構,我們無法訪問。
TOPIC SWITCH!
不適合你,你的老師犯了一個錯誤。如果查看上面的foo_pointers類型的sizeof(),會發現它返回指向該結構的指針的大小,而不是結構的大小。對於32位平臺,這是4個字節,對於64位平臺是8個字節。這是因爲我們輸入了一個指向結構的指針,而不是結構本身。 sizeof(pStudentRecord)將返回4.
因此,您不能以明顯的方式爲結構本身分配空間!然而,編譯器允許這種愚蠢。 pStudentRecord不是可以用來有效分配內存的名稱/類型,它是指向匿名「概念」結構的指針,但我們可以將其大小提供給編譯器。
pStudnetRecord g_ppRecords [2]; pStudentRecord * record = malloc(sizeof(* g_ppRecords [1]));
一個更好的做法是做到這一點:
typedef struct { ... } StudentRecord; // Struct
typedef StudentRecord* pStudentRecord; // Pointer-to struct
現在,我們不得不做出結構StudentRecord的,以及指向他們pStudentRecord的,以明確的方式的能力。
雖然你不得不使用的方法是非常糟糕的做法,但目前這不是一個問題。讓我們回到我們使用整數的簡單示例。
如果我想要使typedef複雜化我的生活但解釋這裏發生的概念怎麼辦?讓我們回到舊的int代碼。
typedef int* array_of_ints;
int *array1[4];
int **array2 = malloc(sizeof(int *) * 4); // Equivalent-ish to the line above
array_of_ints *array3 = malloc(sizeof(array_of_ints) * 4);
int a, b, c, d;
*array1[0] = &a; *array1[1] = &b; *array1[2] = &c; *array1[3] = &d;
*array2[0] = &a; *array2[1] = &b; *array2[2] = &c; *array2[3] = &d;
*array3[0] = &a; *array3[1] = &b; *array3[2] = &c; *array3[3] = &d;
正如你所看到的,我們可以用我們的pStudentRecord使用:
pStudentRecord array1[4];
pStudentRecord *array2 = malloc(sizeof(pStudentRecord) * 4);
把一切融合在一起,它遵循邏輯上:
array1[0]->firstName = "Christopher";
*array2[0]->firstName = "Christopher";
是等價的。 (注意:不要像上面那樣完成;如果你知道你已經有了足夠的空間,那麼在運行時將一個char *指針賦給一個字符串只是確定的)。
這只是真正帶來了最後一點。我們如何處理所有這些我們malloc'd的內存?我們如何釋放它?
free(array1);
free(array2);
還有一個關於指針,匿名結構的typedefs和其他東西的深夜課程的結束。
指針只是指向一個地址。您可以根據需要從該地址開始保留儘可能多的內存(直到空間用完爲止)。 – chris
我認爲這是一個很差的問題,你明白可以用這種方式定義數組,因爲你嘗試爲它分配一個空間,所以你在問什麼?,僅僅爲指針分配一個空間是不夠的結構,這是btw pStudentRecord而不是pSt ... ord *,爲了使用它,你還需要爲struct it自己分配一個地方! – Michael