Структура Typedef объявлена как два типа: "typedef struct x {..} X, * XPointer"
Извините, если это было задано раньше, я даже не был уверен, что искать, чтобы придумать это.
Когда я создаю typedef struct
, я обычно делаю что-то вроде этого:
typedef struct myStruct {
int a;
int b;
struct myStruct *next;
} MyStruct;
Итак, я объявляю его с MyStruct
в конце. Затем, когда я создаю функции, которые передают это как параметр, я пишу
int doSomething(MyStruct *ptr){
}
Тем не менее, я сотрудничаю с другом в проекте, и я столкнулся с его стилем кодирования, который также должен объявить *MyStructP
следующим образом:
typedef struct myStruct {
int a;
int b;
struct myStruct *next;
} MyStructR, *MyStructP;
И затем он использует MyStructP
в своих функциях, поэтому его параметры выглядят так:
int doSomething(MyStructP)
Поэтому ему не нужно использовать *
в списке параметров. Это меня смутило, потому что, когда я смотрю список параметров, я всегда ищу *
, чтобы определить, является ли arg указателем или нет. Кроме того, я создаю функцию, которая принимает структуру, которую я создал, и структуру, которую он создал, поэтому у моего аргумента есть *, а его нет. Ультра запутанный!!
Может кто-нибудь дать прозрение/сравнение/совет по различиям между ними? Плюсы? Минусы? Какой путь лучше или хуже, или более широко используется? Любая информация вообще. Спасибо!
Ответы
Ответ 1
Стиль кодирования ядра Linux говорит, чтобы избежать этих типов typedefs:
Глава 5: Typedefs
Пожалуйста, не используйте такие вещи, как "vps_t".
Ошибочно использовать typedef для структур и указателей. Когда вы видите
vps_t a;
в источнике, что это значит?
В отличие от этого, если он говорит
struct virtual_container *a;
вы действительно можете сказать, что такое "а".
Ответ 2
Обычно считается скрытым указателем, скрывающим указатели за typedefs, если они не предназначены для непрозрачных дескрипторов (например, SDL_GLContext
- это void*
).
Это не так, я согласен с вами в том, что это более запутанно, чем помогает.
Ответ 3
Некоторым людям нравится придумывать идеи из венгерской нотации, когда они называют переменные. И некоторые люди принимают эту концепцию дальше, когда они называют типы.
Я думаю, что это вопрос вкуса.
Однако, я думаю, что это заслоняет вещи (например, в вашем примере), потому что вам нужно будет выкопать декларацию имени, чтобы найти его тип. Я предпочитаю, чтобы вещи были очевидными и явными, и я бы избегал таких имен типов.
(И помните, typedef
не вводит новый тип, а просто новое имя, которое псевдонизирует новый тип.)
Ответ 4
Основная причина, по которой люди иногда указывают указатели typedef, - представлять тип в качестве объекта "черного ящика" программисту и позволять его реализацию в будущем легче изменять.
Например, возможно, сегодня этот тип является указателем на структуру, но завтра тип становится индексом в какую-либо таблицу, дескриптором/ключом какого-либо типа или файловым дескриптором. Typedef'ing таким образом говорит программисту, что они не должны пытаться делать то, что они обычно делают с указателем, например, сравнивая его с 0/NULL, разыменовывая его (например, - напрямую обращающийся к членам), увеличивая его и т.д. В качестве кода может стать нарушенным в будущем. Разумеется, используя соглашение об именах, например, ваш друг, который показывает и кодирует, что основная реализация на самом деле является указателем, конфликтует с этой целью.
Другая причина для этого - сделать такую ошибку менее вероятной:
myStructR *ptr1, ptr2;
myStructP ptr3, ptr4;
Этот довольно слабый соус, так как компилятор обычно поймает вас на неправильном использовании ptr2
позже, но это причина, данная для этого.