2009-09-24 4 views
5

Otwarcie codebase PostgreSQL, widzę, że znaczna część kod C jest napisane przez posiadające wskaźniki z -> notacji w taki sposób, że:C i wskaźnik notacja

(foo)->next = 5; 

wiem, że notacja wskaźnik ma poziomy pierwszeństwa, takie, że -> = (* foo). i nie jest taki sam jak * foo.

Czy jednak oznacza to coś, gdy nawiasy znajdują się poza nazwą zmiennej i odsyłają adres następnego lub jest to tylko konwencja, która jest endemiczna dla stylu kodowania?

Odpowiedz

6

Jest to konwencja kodowania, której wcześniej nie widziałem.

Ale to niczego nie zmienia.

(foo)->next = 5; 

jest dokładnie równoważne

foo->next = 5; 
+0

Niesamowite, dzięki. Tak właśnie myślałem i okazało się to szczególnie dziwne, ponieważ było wszędzie w bazie kodu. – mduvall

+1

Aby się na nim rozwinąć, powód, dla którego użyjesz tej konstrukcji, jest jak pasem bezpieczeństwa, na wypadek, gdyby foo było makro. Z tego samego powodu niektóre przewodniki w stylu C (na przykład FreeBSD) sugerują, że wszystkie zwrotne instrukcje mają formę return (x); zamiast tylko zwracać x; – Benno

+1

Chociaż jeśli 'foo' był makro, dobrze byłoby mieć go w pełni nawiasowany, np. '#define foo (blargity-> blah)' –

1

Nie ma znaczenia. Nawias nie ma znaczenia, ponieważ wyrażenie wewnątrz nich jest tak proste. Zasadniczo jest to

(*(foo)).next = 5; 

Co, jak widać, jest obcym zestawem nawiasów. Jeśli tak działa projekt, idź do niego. W przeciwnym razie, wydaje mi się, że wygląda okropnie, więc starałbym się go nie używać.

+0

Czy chodziło Ci o '' (* (foo)). next = 5; ''? –

+0

Oh. Dobrze. Przynajmniej teraz czuję, że istnieje powód, dla którego nie mogę skupić się na mojej pracy domowej. Dzięki za wskazanie, a dzięki Robertowi za naprawienie. –

2

Jest to konwencja kodowania dla bezpieczeństwa.

W prostym kodzie, gdzie foo jest tylko wskaźnikiem, pareny są zbędne.

(foo)->next = 5; 

jednak rozważyć, czy istnieje lub był szansa, że ​​foo może być określony przez makro więc jest to bardziej skomplikowane wyrażenie.

W takim przypadku pareny mogą być wymagane, aby uniknąć błędu kompilatora lub, co gorsza, uniknąć niepoprawnego pierwszeństwa. Wyobraź sobie, że ona tłumaczona na brzydkiego wyrazu jak:

(++get_foo())->next = 5; 

lub wspólnego Obsada:

((db_record*)foo_ptr)->next = 5; 

Coś pamiętać z idiomatycznym kodu C jest, że makra były często wykorzystywane jako mechanizm abstrakcji dla rzeczy, które możemy robić bardziej wyraźnie w innych językach ;-)

+0

Dowolne makro, które nie pasuje do rozszerzenia, jest problemem. IMHO zadaniem makrowspólnoty jest zapewnienie własnego bezpieczeństwa użytkowania, a nie pracy makrotelefonu. –