program tip

C ++에서 'struct'와 'typedef struct'의 차이점은 무엇입니까?

radiobox 2020. 9. 29. 07:32
반응형

C ++에서 'struct'와 'typedef struct'의 차이점은 무엇입니까?


C ++에서 다음과 같은 차이점이 있습니까?

struct Foo { ... };

typedef struct { ... } Foo;

C ++에서는 미묘한 차이 만 있습니다. 그것은 차이를 만드는 C의 홀드 오버입니다.

C 언어 표준 ( C89 §3.1.2.3 , C99은 §6.2.3C11 §6.2.3 ) 위임 식별자를 포함한 상이한 범주의 네임 스페이스를 분리 태그 식별자 (대 struct/ union/ enum그리고) 일반 ID (위한 typedef다른 식별자) .

방금 말한 경우 :

struct Foo { ... };
Foo x;

Foo태그 네임 스페이스에만 정의되어 있기 때문에 컴파일러 오류가 발생 합니다.

다음과 같이 선언해야합니다.

struct Foo x;

를 참조하고 싶을 때마다 Foo항상 struct Foo. 이것은 짜증나게 빠르게 진행되므로 다음을 추가 할 수 있습니다 typedef.

struct Foo { ... };
typedef struct Foo Foo;

이제 struct Foo(태그 네임 스페이스에서) 및 Foo일반 식별자 네임 스페이스에서 모두 동일한 것을 참조 Foo하며 struct키워드 없이 유형의 객체를 자유롭게 선언 할 수 있습니다 .


구성 :

typedef struct Foo { ... } Foo;

선언과 typedef.


드디어,

typedef struct { ... } Foo;

익명 구조를 선언하고 typedef이를 위해 생성 합니다. 따라서이 구성을 사용하면 태그 네임 스페이스에 이름이없고 typedef 네임 스페이스에 이름 만 있습니다. 이것은 또한 앞으로 선언 될 수 없음을 의미합니다. 포워드 선언을하려면 네임 스페이스 태그에 이름을 지정해야합니다 .


C ++에서 모든 struct/ union/ enum/ class선언 typedef은 동일한 이름을 가진 다른 선언에 의해 이름이 숨겨지지 않는 한 암시 적으로 'ed'된 것처럼 작동 합니다. 자세한 내용은 Michael Burr의 답변 을 참조하십시오.


에서 이 DDJ 문서 , 단 삭스는 당신이 당신의 구조체 typedef에하지 않으면 버그를 통해 크리프 수있는 하나 개의 작은 영역을 설명 (및 클래스를!)

원하는 경우 C ++가 다음과 같이 모든 태그 이름에 대해 typedef를 생성한다고 상상할 수 있습니다.

typedef class string string;

불행히도 이것은 완전히 정확하지 않습니다. 그렇게 간단했으면 좋겠지 만 그렇지 않습니다. C ++는 C와의 비 호환성을 도입하지 않고는 구조체, 공용체 또는 열거 형에 대해 이러한 typedef를 생성 할 수 없습니다.

예를 들어 C 프로그램이 함수와 status라는 구조체를 모두 선언한다고 가정합니다.

int status(); struct status;

다시 말하지만 이것은 나쁜 습관 일 수 있지만 C입니다.이 프로그램에서 상태 (그 자체로)는 기능을 나타냅니다. 구조체 상태는 유형을 나타냅니다.

C ++가 태그에 대한 typedef를 자동으로 생성 한 경우이 프로그램을 C ++로 컴파일하면 컴파일러에서 다음을 생성합니다.

typedef struct status status;

불행히도이 유형 이름은 함수 이름과 충돌하고 프로그램이 컴파일되지 않습니다. 이것이 C ++가 각 태그에 대해 단순히 typedef를 생성 할 수없는 이유입니다.

In C++, tags act just like typedef names, except that a program can declare an object, function, or enumerator with the same name and the same scope as a tag. In that case, the object, function, or enumerator name hides the tag name. The program can refer to the tag name only by using the keyword class, struct, union, or enum (as appropriate) in front of the tag name. A type name consisting of one of these keywords followed by a tag is an elaborated-type-specifier. For instance, struct status and enum month are elaborated-type-specifiers.

Thus, a C program that contains both:

int status(); struct status;

behaves the same when compiled as C++. The name status alone refers to the function. The program can refer to the type only by using the elaborated-type-specifier struct status.

So how does this allow bugs to creep into programs? Consider the program in Listing 1. This program defines a class foo with a default constructor, and a conversion operator that converts a foo object to char const *. The expression

p = foo();

in main should construct a foo object and apply the conversion operator. The subsequent output statement

cout << p << '\n';

should display class foo, but it doesn't. It displays function foo.

This surprising result occurs because the program includes header lib.h shown in Listing 2. This header defines a function also named foo. The function name foo hides the class name foo, so the reference to foo in main refers to the function, not the class. main can refer to the class only by using an elaborated-type-specifier, as in

p = class foo();

The way to avoid such confusion throughout the program is to add the following typedef for the class name foo:

typedef class foo foo;

immediately before or after the class definition. This typedef causes a conflict between the type name foo and the function name foo (from the library) that will trigger a compile-time error.

I know of no one who actually writes these typedefs as a matter of course. It requires a lot of discipline. Since the incidence of errors such as the one in Listing 1 is probably pretty small, you many never run afoul of this problem. But if an error in your software might cause bodily injury, then you should write the typedefs no matter how unlikely the error.

I can't imagine why anyone would ever want to hide a class name with a function or object name in the same scope as the class. The hiding rules in C were a mistake, and they should not have been extended to classes in C++. Indeed, you can correct the mistake, but it requires extra programming discipline and effort that should not be necessary.


One more important difference: typedefs cannot be forward declared. So for the typedef option you must #include the file containing the typedef, meaning everything that #includes your .h also includes that file whether it directly needs it or not, and so on. It can definitely impact your build times on larger projects.

Without the typedef, in some cases you can just add a forward declaration of struct Foo; at the top of your .h file, and only #include the struct definition in your .cpp file.


There is a difference, but subtle. Look at it this way: struct Foo introduces a new type. The second one creates an alias called Foo (and not a new type) for an unnamed struct type.

7.1.3 The typedef specifier

1 [...]

A name declared with the typedef specifier becomes a typedef-name. Within the scope of its declaration, a typedef-name is syntactically equivalent to a keyword and names the type associated with the identifier in the way described in Clause 8. A typedef-name is thus a synonym for another type. A typedef-name does not introduce a new type the way a class declaration (9.1) or enum declaration does.

8 If the typedef declaration defines an unnamed class (or enum), the first typedef-name declared by the declaration to be that class type (or enum type) is used to denote the class type (or enum type) for linkage purposes only (3.5). [ Example:

typedef struct { } *ps, S; // S is the class name for linkage purposes

So, a typedef always is used as an placeholder/synonym for another type.


You can't use forward declaration with the typedef struct.

The struct itself is an anonymous type, so you don't have an actual name to forward declare.

typedef struct{
    int one;
    int two;
}myStruct;

A forward declaration like this wont work:

struct myStruct; //forward declaration fails

void blah(myStruct* pStruct);

//error C2371: 'myStruct' : redefinition; different basic types

An important difference between a 'typedef struct' and a 'struct' in C++ is that inline member initialisation in 'typedef structs' will not work.

// the 'x' in this struct will NOT be initialised to zero
typedef struct { int x = 0; } Foo;

// the 'x' in this struct WILL be initialised to zero
struct Foo { int x = 0; };

Struct is to create a data type. The typedef is to set a nickname for a data type.


There is no difference in C++, but I believe in C it would allow you to declare instances of the struct Foo without explicitly doing:

struct Foo bar;

참고URL : https://stackoverflow.com/questions/612328/difference-between-struct-and-typedef-struct-in-c

반응형