Структура 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 позже, но это причина, данная для этого.