Typedef, структура и тип совместимости

Если у меня есть эти две структуры:

struct
{
   int x;
} A;

struct
{
   int x;
} B;

тогда создание A = B; приводит к ошибке компиляции, потому что две анонимные структуры несовместимы.

Однако, если я это сделаю:

typedef struct
{
   int x;
} S;

S A;

S B;

A = B; является юридическим назначением, поскольку они совместимы.

Но почему? С typedef я понимаю, что компилятор делает это, когда встречаются S A и S B:

struct { int x; } A;
struct { int x; } B;

поэтому A и B не должны быть совместимы...

Ответ 1

Каждое объявление анонимной структуры является отдельным типом; вот почему вы получаете несоответствие типа при попытке назначить его другому.

Однако typedef объявляет псевдоним (т.е. новое имя для уже существующего) для типа (он не создает новый тип).

typedef также не простая замена текста, как макрос препроцессора. Ваше выражение

Я понимаю, что компилятор делает это, когда встречаются S A и S B:

struct { int x; } A;
struct { int x; } B;

где ваше понимание неверно.

Когда вы используете псевдоним типа S, как в

S A;
S B;

типы обоих объектов A и B являются одинаковыми по определению и могут быть назначены друг другу.

Ответ 2

Это связано с тем, что C рассматривает каждый немаркированный struct как новый вид struct, независимо от расположения макета. Однако typedef struct { } name; нельзя использовать, если вы хотите использовать struct в связанном списке. Вам нужно будет придерживаться определения тега структуры в этом случае и typedef вместо тега struct.

Ответ 3

struct DistanceInMeter /* Anonymous 1 */
{
  int x; /* distance */
};

struct VolumeInCC /* Anonymous 2 */
{
  int x; /* volume */
};

struct DistanceInMeter A;
struct VolumeInCC B;
...
A = B; /* Something is wrong here */

Уравнение разного типа не всегда имеет смысл и, следовательно, не допускается.

typedef struct DistanceInMeter /* Anonymous 1 */
{
  int x; /* distance */
} Dist_t;
Dist_t C, D;
...
C = D; /* Alright, makes sense */