[英]notation confusion in C when variable is a pointer
當我有一個指針變量f
指向定義為的struct X
時,我對 C 中的符號感到困惑:
struct Y {
int d;
struct X *e;
};
struct X {
int *a;
int b[4];
struct Y c;
};
然后我有這個:
f->c.e->c.e[0].a[0]
我不明白的是部分ce[0].a[0]
。
我不確定ce[0]
是什么,然后ce[0].a[0]
是什么。 (也不確定ce[0]
是否與struct X
的起始地址相距 20 個偏移量)。 假設這里的指針是 4 個字節,整數是 4 個字節。 所以int *a
+ int b[4]
+ int d
= 20 偏移量? 是f->ce->ce[0]
的意思嗎? 有f->ce->ce[3]
嗎? f->ce->ce[4]
? f->ce->ce[5]
?
我很困惑,因為通常對於指針變量說k
,當變量k
指向結構變量時,我總是看到k->x
、 k->y
、 k->l
來引用結構中的變量。 但是在這種情況下,我看到了ce->ce[0].a[0]
的符號。 e[0].a[0]
有效嗎? 我猜e[0]
不是指針,因為如果它是指針e[0]
必須始終使用->
符號來引用它指向的結構中的變量,但是因為它使用 (dot .
) 代替of (arrow ->
), e[0].a[0]
所以我猜在這種情況下e[0]
不是指針,對吧?
那么我對這里給定的struct X
、 struct Y
和給定的指針變量f
中的ce[0].a[0]
的含義有點困惑。
ce
是指向struct X
的指針,因此ce[0]
是ce
指向的struct X
。
如果ce
是指向 4 struct Y
數組的第一個元素的指針,則該數組的 4 個元素可以稱為ce[0]
、 ce[1]
、 ce[2]
和ce[3]
。
對於所有指針p
, p[0]
等價於*p
或*(p + 0)
(甚至0[p]
)。
在這種情況下, f->ce->ce[0].a[0]
等價於f->ce->ce->a[0]
和*f->ce->ce->a
。 使用哪種語法是風格和可讀性的問題。 當索引為或可以不為零時,使用[]
的數組語法通常更具可讀性,如果是指向單個對象的指針,則首選->
語法。
實際的實現細節,例如指針和整數大小在這里無關緊要,但請記住,結構中成員的偏移量可能會受到對齊約束的影響:例如在大多數當前的 64 位系統中,一個int
仍然有 4字節,但指針使用 8 個字節,因此struct Y
中e
的偏移量必須與8
的倍數對齊,因此是8
,而不是4
。 在d
和e
之間插入 4 個填充字節。 另請注意,如果d
旨在存儲由e
指向的數組中的元素數,則它可能應該使用size_t
類型定義。
混淆來自於在 C 中使用指針的多種方式。
聲明一個簡單的數組如下:
<type> <name>[<size>];
// More concretely
int array_of_ints[5];
// Accessing its elements is straightforward
array_of_ints[0] = 42;
但是,如果您無法提前知道尺寸怎么辦? 您必須使用例如malloc
分配內存,它為您提供指向數組開頭的指針:
int * array_of_ints = malloc(sizeof(int) * 5);
// Access its elements the same way as arrays declared on the stack
array_of_ints[0] = 42;
為什么相同的語法可以用於兩種類型( int[5]
與int *
)?
這是因為在引擎蓋下編譯器以完全相同的方式對待它。 數組的名稱實際上是指向它的第一個元素的指針,我們可以在這里看到:
void foo(int * array)
{
printf("%d\n", *array); // *array and array[0] are interchangeable
}
int bar()
{
int array[5];
array[0] = 42;
foo(array);
}
所以一個數組可以衰減為一個指針。 該語言允許您使用[]
運算符,因為編譯器實際上使用指針算法對其進行了翻譯:
array[0]
與*array
相同,但更准確地說,與*(array + 0)
相同。
那么你怎么知道你有一個指向單個值的指針還是一個指向數組第一個值的值的指針呢? 好吧,沒有上下文,你不能。 從孤立函數的角度來看,您無法知道采用char *
參數是否意味着它是字符串參數或指向單個 char 變量的指針。 開發人員可以通過傳遞數組的大小或正確命名變量(例如char * str
與char * c
)、編寫文檔等方式來明確說明。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.