ProgramingTip

typedef 골대 골 정의

bestdevel 2020. 9. 29. 08:14
반응형

typedef 골대 골 정의 [중복]


이 질문에 이미 답변이 있습니다.

저는 C 프로그래밍의 궁금하지만 typedef구조를 정의 할 때 사용 하는 것과 사용하지 않는 것의 차이점이 무엇인지 않습니다 typedef. 정말 차이가없는 것 같고 같은 목표를 달성합니다.

struct myStruct{
    int one;
    int two;
};

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

일반적인 관용구는 다음 두 가지를 모두 사용합니다.

typedef struct X { 
    int x; 
} X;

그들은 서로 다른 정의입니다. 토론을 더 명확하게하기 위해 문장을 분할하겠습니다.

struct S { 
    int x; 
};

typedef struct S S;

첫 번째 줄 S에서는 내 에서 식별자를 정의합니다 (C ++ 의미가 아님). 이를 사용하고 인수 유형을 다음과 같이 정의하여 새로 정의 된 유형의 변수 또는 함수 인수를 정의 할 수 있습니다 struct S.

void f( struct S argument ); // struct is required here

두 번째 줄 S은 전역 이름 공간에 유형 추가 할 수있는 다음과 같이 사용할 수 있습니다.

void f( S argument ); // struct keyword no longer needed

식별자 이름 공간 두이 다르기 S때문에 동일한 식별자를 재정의하는 것이 아니라 다른 위치에 다른 식별자를 만드는 것이기 때문에 구조체와 전역 공간에서 모두 정의하는 [해석] 오류가 아닙니다.

차이를 더 명확하게 비용 :

typedef struct S { 
    int x; 
} T;

void S() { } // correct

//void T() {} // error: symbol T already defined as an alias to 'struct S'

식별자가 다른 공간에 보관할 때와 같은 이름으로 함수를 정의 할 때와 같은 typedef식별자가 충돌 할 수 없습니다 .

C ++에서는 기호를 찾는 규칙이 미묘하게 변경 되었기 때문에 변경되었습니다. C ++는 여전히 두 개의 다른 식별자 공간을 유지하지만 C에서와 달리 클래스 식별자 공간 내에서만 정의 할 때 struct / class 키워드를 제공 할 필요가 없습니다.

 // C++
struct S { 
    int x; 
}; // S defined as a class

void f( S a ); // correct: struct is optional

식별자가 정의 된 위치가 아니라 검색 규칙이 어떻게 변경됩니다. 컴파일러는 전역 식별자 테이블을 검색하고 S찾지 못한 후에 S클래스 식별자 내 검색합니다 .

이전에 제시된 코드는 동일한 방식으로 작동합니다.

typedef struct S { 
    int x; 
} T;

void S() {} // correct [*]

//void T() {} // error: symbol T already defined as an alias to 'struct S'

S두 번째 줄 함수를 정의한 후에는 S는 컴파일러에 의해 자동으로 해석 될 수있는 인수를 자동으로 생성하거나 해당 유형의 인수를 정의한 결과 struct키워드 를 포함하여 대체 해야합니다 .

// previous code here...
int main() {
    S(); 
    struct S s;
}

structtypedef매우 다른 두 가지 있습니다.

struct키워드는 정의, 또는 구조 유형을 참조하는 데 사용됩니다. 예를 들면 다음과 같습니다.

struct foo {
    int n;
};

라는 새 유형을 만듭니다 struct foo. 이름 foo태그입니다 . struct태그와 기타 식별자가 고유 한 네임 스페이스 에 있기 때문에 키워드 바로 앞에 오는 경우에만 의미 있습니다 . (이것은 namespaces 의 C ++ 개념과 비슷하지만 훨씬 더 제한적 입니다.)

A typedef는 이름에도 불구하고 새로운 유형을 정의하지 않습니다. 단순히 기존 유형에 대한 새 이름을 만듭니다. 예를 들면 다음과 같습니다.

typedef int my_int;

my_int의 새 이름입니다 int. my_int하고 int있습니다 정확히 같은 유형입니다. 마찬가지로 struct정의가 주어지면 다음과 같이 작성할 수 있습니다.

typedef struct foo foo;

유형에 이미 이름이 struct foo있습니다. typedef선언은 동일한 유형의 새 이름을 준다 foo.

구문은 당신이를 결합 할 수 structtypedef단일 선언으로 :

typedef struct bar {
    int n;
} bar;

이것은 일반적인 관용구입니다. 이제이 구조 유형을로 struct bar또는 그대로으로 참조 할 수 있습니다 bar.

typedef 이름은 선언이 끝날 때까지 표시되지 않습니다. 구조에 자신에 대한 포인터가 포함 된 경우 struct버전을 사용하여 참조해야합니다.

typedef struct node {
    int data;
    struct node *next; /* can't use just "node *next" here */
} node;

일부 프로그래머는 struct 태그와 typedef 이름에 대해 고유 한 식별자를 사용합니다. 제 생각에는 그럴만 한 이유가 없습니다. 동일한 이름을 사용하는 것은 완벽하게 합법적이며 동일한 유형임을 더 명확하게합니다. 다른 식별자를 사용해야하는 경우 최소한 일관된 규칙을 사용하십시오.

typedef struct node_s {
    /* ... */
} node;

(개인적으로는 생략하고 typedef타입을라고 부르는 것을 선호합니다 struct bar. typedef약간의 타이핑을 절약 할 수 있지만 구조 타입이라는 사실을 숨 깁니다. 타입을 불투명하게하고 싶다면 이것은 좋은 일이 될 수 있습니다. 코드는 멤버 n를 이름 으로 지칭 할 것입니다 . 그러면 불투명하지 않습니다. 눈에 띄는 구조이고 제 생각에는 구조라고 부르는 것이 합리적이라고 생각합니다. 어느 쪽이든 작성된 코드를 읽고 이해할 준비가되었습니다.)

(C ++에는 다른 규칙이 있습니다.를 선언 하면 typedef 없이도 struct blah유형을 그냥으로 참조 할 수 있습니다 blah. typedef를 사용하면 C 코드가 C ++와 비슷해집니다.


지적되지 않은 또 다른 차이점은 구조체에 이름 (예 : struct myStruct)을 지정하면 구조체의 전방 선언을 제공 할 수 있다는 것입니다. 따라서 다른 파일에 다음과 같이 작성할 수 있습니다.

struct myStruct;
void doit(struct myStruct *ptr);

정의에 액세스 할 필요없이. 내가 추천하는 것은 두 가지 예를 결합하는 것입니다.

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

이것은보다 간결한 typedef 이름의 편리함을 제공하지만 필요한 경우 전체 구조체 이름을 사용할 수 있습니다.


C (C ++ 아님)에서는 다음과 같은 구조체 변수를 선언해야합니다.

struct myStruct myVariable;

myStruct myVariable;대신 사용할 typedef있도록 struct 를 사용할 수 있습니다 .

typedef struct myStruct someStruct;
someStruct myVariable;

당신은 결합 할 수 있습니다 struct정의하고 typedef익명을 선언 한 성명에서 그것을이야 struct하고 typedef그것을이야.

typedef struct { ... } myStruct;

struct없이 사용 typedef하면 항상 작성해야합니다.

struct mystruct myvar;

쓰는 것은 불법입니다

mystruct myvar;

를 사용하면 더 이상 접두사 typedef가 필요하지 않습니다 struct.


C에서, 구조, 노동 조합 및 열거의 유형 지정자 키워드는 필수 당신은 항상 유형의 이름 (그 앞에해야 즉, 태그를 포함) struct, union또는 enum유형을 참조 할 때.

을 사용하여 키워드를 제거 할 수 있습니다. typedef은 객체를 선언 할 때 실제 유형이 더 이상 표시되지 않으므로 정보를 숨기는 형태입니다.

따라서 몇 번의 키 입력 만 저장하는 것이 아니라 실제로이 정보를 숨기고 싶을 때만이 작업을 수행 하는 것이 좋습니다 (예 : Linux 커널 코딩 스타일 가이드 , 5 장 참조) .

a를 사용해야하는 경우의 예는 typedef해당 접근 자 함수 / 매크로에서만 사용되는 불투명 유형입니다.


다음 코드는 별칭이있는 익명 구조체를 만듭니다 myStruct.

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

구조에 대한 식별자를 지정하지 않기 때문에 별칭없이 참조 할 수 없습니다.


.NET과 함께 포워드 선언을 사용할 수 없습니다 typedef struct.

struct당신은 앞으로 선언에 실제 이름을하지 않아도 자체는 익명의 유형입니다.

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

다음과 같은 전방 선언은 작동하지 않습니다.

struct myStruct; //forward declaration fails

void blah(myStruct* pStruct);

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

차이점은 struct.

해야 할 첫 번째 방법 :

struct myStruct aName;

두 번째 방법은 키워드를 제거하는 것 struct입니다.

myStruct aName;

typedef그것이 다른 구조와 같이, 데이터 형식에 새 이름을 부여하는 데 사용된다. 이 경우 대부분 코드를 더 깔끔하게 만들기 위해 수행됩니다.

struct myStruct blah;

myStruct blah;

후자의 예에서는 구조를 사용할 때 struct 키워드를 생략합니다. 따라서 코드의 모든 곳에서 다음과 같이 작성할 수 있습니다.

myStruct a;

대신에

struct myStruct a;

이것은 타이핑을 절약하고 더 읽기 쉬울 수도 있지만 이것은 취향의 문제입니다.


나는 이것에 대해 약간의 설명이 필요하다는 것을 알았다. C와 C ++는 유형을 다르게 정의하지 않습니다. C ++는 원래 C 위에 추가 된 포함 세트에 불과했습니다.

오늘날 거의 모든 C / C ++ 개발자가 갖고있는 문제는 a) 대학이 더 이상 기본 사항을 가르치지 않고 b) 사람들이 정의와 선언의 차이를 이해하지 못한다는 것입니다.

이러한 선언과 정의가 존재하는 유일한 이유는 링커가 구조의 필드에 대한 주소 오프셋을 계산할 수 있기 때문입니다. 이것이 대부분의 사람들이 실제로 잘못 작성된 코드를 사용하지 않는 이유입니다. 컴파일러가 주소 지정을 결정할 수 있기 때문입니다. 문제는 누군가가 대기열이나 연결 목록과 같은 작업을 진행하거나 O / S 구조를 피기 백하려고 할 때 발생합니다.

선언은 'struct'로 시작하고 정의는 'typedef'로 시작합니다.

또한 구조체에는 정방향 선언 레이블과 정의 된 레이블이 있습니다. 대부분의 사람들은 이것을 모르고 정방향 선언 레이블을 정의 레이블로 사용합니다.

잘못된:

struct myStruct
   {
   int field_1;
   ...
   };

그들은 구조에 레이블을 지정하기 위해 앞으로 선언을 사용 했으므로 이제 컴파일러가이를 인식하고 있지만 실제 정의 된 유형은 아닙니다. 컴파일러는 주소 지정을 계산할 수 있습니다. 그러나 이것은 제가 잠시 보여줄 이유 때문에 의도 된 방식이 아닙니다.

이 선언 형식을 사용하는 사람들은 공식적인 새로운 유형이 아니기 때문에 실제로 모든 참조에 항상 'struct'를 넣어야합니다.

대신 자신을 참조하지 않는 구조는 다음과 같이 선언하고 정의해야합니다.

typedef struct
   {
   field_1;
   ...
   }myStruct;

이제 실제 유형이며 사용하면 'struct'라는 단어를 앞에 추가하지 않고도 'myStruct'로 사용할 수 있습니다.

해당 구조에 대한 포인터 변수를 원하면 보조 레이블을 포함하십시오.

typedef struct
   {
   field_1;
   ...
   }myStruct,*myStructP;

이제 그 구조에 대한 포인터 변수가 있습니다.

앞으로 선언-

자, 여기 포워드 선언이 어떻게 작동하는지 멋진 것들이 있습니다. 연결 목록이나 큐 요소와 같이 자신을 참조하는 형식을 만들려면 정방향 선언을 사용해야합니다. 컴파일러는 맨 끝에 세미콜론에 도달 할 때까지 정의 된 구조를 고려하지 않으므로 해당 지점 이전에 선언됩니다.

typedef struct myStructElement
   {
   myStructElement*  nextSE;
   field_1;
   ...
   }myStruct;

이제 컴파일러는 전체 유형이 아직 무엇인지 모르지만 앞으로 참조를 사용하여 참조 할 수 있음을 알고 있습니다.

구조를 올바르게 선언하고 typedef하십시오. 실제로 이유가 있습니다.

참고 URL : https://stackoverflow.com/questions/1675351/typedef-struct-vs-struct-definitions

반응형