왜 C에서 구조체를 이렇게 자주 typedef해야합니까?


406

아래와 같은 구조로 구성된 많은 프로그램을 보았습니다.

typedef struct 
{
    int i;
    char k;
} elem;

elem user;

왜 그렇게 자주 필요합니까? 특정한 이유나 적용 가능한 영역이 있습니까?


14
더 철저하고 정확한 답변 : stackoverflow.com/questions/612328/…
AbiusX

단점은 익명의 구조체로 링크 목록을 만들 수 없다고 생각합니다 struct * ptr. 구조체 내부의 줄 이 오류를 일으킬 수 있기 때문입니다
Raghib Ahsan

9
'보다 철저하고 정확한 답변'은 C ++의 구조체와 typedef 구조체의 차이점이며 , C와 C ++ 사이에는 C에 대한 질문에 그 대답이 전적으로 적합하지 않은 C와 C ++의 차이가 있습니다.
Jonathan Leffler

이 질문에는 중복 된 typedef 구조체 대 구조체 정의 가 있으며 훌륭한 정의 도 있습니다.
Jonathan Leffler 2016 년

2
OTOH, kernel.org/doc/html/v4.10/process/coding-style.html 은 그러한 typedef를하지 말아야한다고 말합니다.
glglgl

답변:


454

Greg Hewgill이 말했듯이 typedef는 더 이상 struct모든 곳 을 쓸 필요가 없음을 의미합니다 . 키 스트로크를 절약 할뿐만 아니라 smidgen에 더 추상화를 제공하므로 코드를 더 깨끗하게 만들 수 있습니다.

같은 것

typedef struct {
  int x, y;
} Point;

Point point_new(int x, int y)
{
  Point a;
  a.x = x;
  a.y = y;
  return a;
}

"struct"키워드를 모든 곳에서 볼 필요가 없을 때 더 깨끗해집니다. 실제로 언어에 "Point"라는 유형이있는 것처럼 보입니다. 다음에 typedef내가 추측하는 경우가 있습니다.

또한 귀하의 예제 (및 광산)는 struct 자체 이름 지정을 생략했지만 실제로는 이름 지정이 불투명 한 유형을 제공하려는 경우에도 유용합니다. 그런 다음 헤더에 다음과 같은 코드가 있습니다.

typedef struct Point Point;

Point * point_new(int x, int y);

그런 다음 struct구현 파일에 정의 를 제공 하십시오.

struct Point
{
  int x, y;
};

Point * point_new(int x, int y)
{
  Point *p;
  if((p = malloc(sizeof *p)) != NULL)
  {
    p->x = x;
    p->y = y;
  }
  return p;
}

후자의 경우, 정의는 헤더 파일의 사용자에게 숨겨져 있기 때문에 Point by 값을 반환 할 수 없습니다. 이것은 예를 들어 GTK + 에서 널리 사용되는 기술 입니다.

업데이트typedef 숨기기를 사용 struct하는 것이 나쁜 생각 으로 여겨지는 C 프로젝트도 있습니다. 리눅스 커널은 아마도 가장 잘 알려진 프로젝트 일 것입니다. Linus의 화난 단어에 대해서는 Linux 커널 코딩 스타일 문서의 5 장을 참조하십시오 . :) 내 요점은 문제의 "반드시"가 아마도 돌로 설정되어 있지 않다는 것입니다.


58
밑줄과 대문자로 된 식별자를 사용해서는 안되며 예약되어 있습니다 (섹션 7.1.3 단락 1 참조). 많은 문제가되지는 않지만, 사용할 때 기술적으로 정의되지 않은 동작입니다 (7.1.3 단락 2).
dreamlax

16
@ dreamlax : 다른 사람들에게 명확하지 않은 경우 , 밑줄과 대문자 로만 식별자를 시작 하면 안됩니다. 식별자 중간에 자유롭게 사용할 수 있습니다.
brianmearns

12
여기에 주어진 예제 (typedef가 "전체 위치"를 사용하여 "struct"를 사용하지 못하게하는 예제)가 실제로 "struct"라는 단어를 한 번만 사용하므로 typedef가없는 동일한 코드보다 길다는 점이 흥미 롭습니다. 얻은 추상화의 smidgen은 추가 난독 화와 유리한 비교를 거의하지 않습니다.
William Pursell

7
@Rerito 참고로, 페이지 166 C99 초안 , 밑줄 및 대문자 중 하나 또는 다른 밑줄로 시작하는 모든 확인 시험 과학 ERS는 항상 사용하기 위해 예약되어 있습니다. 그리고 확인 시험 Fi를 모두 일반 및 태그 이름 공간에서 Fi를 제작 범위와 ERS으로 밑줄로 시작하는 모든 확인 시험 과학 ERS는 항상 사용하기 위해 예약되어 있습니다.
e2-e4

10
흥미롭게도 리눅스 커널 코딩 지침에 따르면 typedef 사용에 대해 훨씬 더 보수적이어야한다고합니다 (섹션 5) : kernel.org/doc/Documentation/CodingStyle
gsingh2011

206

얼마나 많은 사람들이이 잘못을 저지르는지는 놀랍습니다. C로 구조체를 typedef하지 말고, 큰 C 프로그램에서 이미 매우 오염 된 전역 네임 스페이스를 불필요하게 오염시킵니다.

또한 태그 이름이없는 typedef의 구조체는 헤더 파일 간의 순서 관계를 불필요하게 부과하는 주요 원인입니다.

치다:

#ifndef FOO_H
#define FOO_H 1

#define FOO_DEF (0xDEADBABE)

struct bar; /* forward declaration, defined in bar.h*/

struct foo {
  struct bar *bar;
};

#endif

typedef를 사용하지 않는 그러한 정의로, compiland 유닛이 foo.h를 포함하여 FOO_DEF정의 에 도달 할 수 있습니다. foo구조체 의 'bar'멤버를 역 참조하지 않으면 "bar.h"파일을 포함 할 필요가 없습니다.

또한 네임 스페이스가 태그 이름과 멤버 이름간에 다르기 때문에 다음과 같이 매우 읽기 쉬운 코드를 작성할 수 있습니다.

struct foo *foo;

printf("foo->bar = %p", foo->bar);

네임 스페이스는 별개이므로 이름 지정 변수와 struct 태그 이름이 일치하는 충돌이 없습니다.

코드를 유지 관리 해야하는 경우 typedef의 구조체를 제거합니다.


37
더 놀라운 점은이 답변을받은 지 13 개월이 지난 후에야 처음으로 그것을 찬성했습니다. typedef'ing 구조체는 C의 가장 큰 남용 중 하나이며 잘 작성된 코드에는 없습니다. typedef는 복잡한 함수 포인터 유형을 난독 처리하는 데 유용하며 실제로는 다른 유용한 목적을 제공하지 않습니다.
William Pursell

28
Peter van der Linden은 또한 자신의 깨달은 책 "Expert C Programming-Deep C Secrets"에서 typedefing 구조체에 대해 소송을 제기합니다. 요점은 : 당신은 무언가가 구조체가 아니라 노조임을 알고 싶어합니다.
Jens

34
Linux 커널 코딩 스타일은 typedefing 구조체를 명시 적으로 금지합니다. 5 장 : Typedefs : " 구조와 포인터에 typedef를 사용 하는 것은 실수 입니다." kernel.org/doc/Documentation/CodingStyle
jasso

63
"struct"를 반복해서 타이핑하면 어떤 이점이 있습니까? 그리고 오염에 대해 말하면 왜 전역 네임 스페이스에서 동일한 이름의 구조체와 함수 / 변수 / typedef를 원하십니까 (동일한 함수에 대한 typedef가 아닌 한)? 안전한 패턴을 사용하는 것 typedef struct X { ... } X입니다. 이렇게하면 짧은 형식 X을 사용하여 정의를 사용할 수있는 곳 어디에서나 구조체를 처리 할 수 ​​있지만 struct X원하는 경우 계속 선언하고 사용할 수 있습니다.
Pavel Minaev

7
나는 개인적으로 typedef를 사용하는 경우가 거의 없으며 다른 사람들이 그것을 사용해서는 안되며 내 스타일이 아니라고 말하지 않을 것입니다. 변수 유형 앞에 구조체를보고 싶으므로 구조체를 즉시 알 수 있습니다. 인수를 입력하기 쉬운 것은 약간 글자가 적고, 단일 문자 인 변수도 입력하기가 쉽고, 자동 완성 기능을 사용하면 요즘 어디서나 struct를 입력하는 것이 얼마나 어려운가요?
Nathan Day

138

Dan Saks의 오래된 기사에서 ( http://www.ddj.com/cpp/184403396?pgno=3 ) :


구조체의 이름을 지정하는 C 언어 규칙은 약간 편 심적이지만 무해합니다. 그러나 C ++의 클래스로 확장 될 때 동일한 규칙으로 버그가 크롤링되지 않습니다.

C에서 이름은

struct s
    {
    ...
    };

태그입니다. 태그 이름은 유형 이름이 아닙니다. 위의 정의에서 다음과 같은 선언은

s x;    /* error in C */
s *p;   /* error in C */

C의 오류입니다. 다음과 같이 작성해야합니다.

struct s x;     /* OK */
struct s *p;    /* OK */

공용체와 열거의 이름도 유형이 아닌 태그입니다.

C에서 태그는 다른 모든 이름 (함수, 유형, 변수 및 열거 상수)과 구별됩니다. C 컴파일러는 다른 모든 이름을 보유한 테이블과 물리적으로 분리되어 있지 않은 경우 개념적으로 심볼 테이블에 태그를 유지합니다. 따라서 C 프로그램이 동일한 범위에서 동일한 철자를 가진 태그와 다른 이름을 모두 가질 수 있습니다. 예를 들어

struct s s;

struct 유형의 변수 s를 선언하는 유효한 선언입니다. 좋은 습관은 아니지만 C 컴파일러는이를 받아 들여야합니다. C가 이런 식으로 설계된 이유에 대한 이론적 근거를 본 적이 없습니다. 나는 항상 그것이 실수라고 생각했지만 거기에 있습니다.

많은 프로그래머 (당신을 포함하여)는 구조체 이름을 타입 이름으로 생각하기를 원하므로 typedef를 사용하여 태그의 별칭을 정의합니다. 예를 들어

struct s
    {
    ...
    };
typedef struct s S;

struct 대신 S를 사용할 수 있습니다.

S x;
S *p;

프로그램은 S를 유형과 변수 (또는 함수 또는 열거 상수)의 이름으로 사용할 수 없습니다.

S S;    // error

이거 좋다

구조체, 공용체 또는 열거 정의의 태그 이름은 선택 사항입니다. 많은 프로그래머들이 구조체 정의를 typedef로 접고 다음과 같이 태그를 생략합니다.

typedef struct
    {
    ...
    } S;

링크 된 기사는 또한 C ++ 동작이 필요하지 않은 C ++ 동작이 어떻게 typedef미묘한 이름 숨기기 문제를 일으킬 수 있는지에 대한 토론을 제공 합니다. 이러한 문제를 방지하려면 typedef언뜻보기에는 불필요 한 것처럼 보이지만 C ++의 클래스와 구조체에도 좋은 아이디어 입니다. C ++ typedef에서 이름 숨기기를 사용하면 잠재적 인 문제의 숨겨진 원인이 아니라 컴파일러에서 알려주는 오류가됩니다.


2
태그 이름이 비 태그 이름과 동일한 경우의 한 가지 예는 기능이있는 (POSIX 또는 Unix) 프로그램에 int stat(const char *restrict path, struct stat *restrict buf)있습니다. 거기에는 stat일반 네임 스페이스와 struct stat태그 네임 스페이스에 기능이 있습니다.
Jonathan Leffler 2016 년

2
당신의 진술, SS; // error .... IS WRONG 제대로 작동합니다. "typedef 태그와 var에 대해 같은 이름을 가질 수 없습니다"라는 말이 잘못되었습니다. pls check
eRaisedToX

63

사용 typedef하면 struct해당 유형의 변수를 선언 할 때마다 쓰지 않아도됩니다 .

struct elem
{
 int i;
 char k;
};
elem user; // compile error!
struct elem user; // this is correct

2
좋아, 우리는 C ++에서 그 문제가 없다. 왜 아무도 C의 컴파일러에서 그 결함을 제거하고 C ++에서와 동일하게 만들지 마십시오. C ++에는 다른 응용 프로그램 영역이 있으므로 고급 기능을 가지고 있습니다. 원래 C?
Manoj Doubts

4
Manoj, 태그 이름 ( "struct foo")은 자신을 참조하는 구조체를 정의해야 할 때 필요합니다. 예를 들어 링크 된 목록의 "다음"포인터. 요컨대, 컴파일러는 표준을 구현하며 이것이 표준이 말하는 것입니다.
Michael Carman

41
C 컴파일러의 결함이 아니며 디자인의 일부입니다. 그들은 C ++의 변경으로 인해 일이 더 쉬워 진다고 생각하지만 C의 동작이 잘못되었다는 것을 의미하지는 않습니다.
Herms

5
불행히도 많은 '프로그래머'는 구조체를 정의한 다음 '관련되지 않은'이름으로 구조체를 typedef합니다 (struct myStruct ...; typedef struct myStruct susan *; 거의 모든 경우에 typedef는 코드를 어지럽히는 것만으로 실제 정의를 숨 깁니다. 변수 / 매개 변수, 코드의 원래 작성자를 포함하여 모든 사람을 잘못 인도합니다.
user3629249

1
@ user3629249 언급 한 프로그래밍 스타일이 끔찍하지만 이것이 typedef일반적으로 구조를 거부하는 이유는 아닙니다 . 당신은 또한 할 수 있습니다 typedef struct foo foo;. 물론 struct키워드는 더 이상 필요하지 않습니다. 우리가 보는 유형 별칭은 구조의 별칭이지만 일반적으로 나쁘지는 않습니다. 결과 유형 별명의 식별자 typedef가 그것이 구조의 별명 인 fe : 를 나타내는 경우도 고려하십시오 typedef struct foo foo_struct;.
RobertS는

38

이 문제의 결과를 항상 typedef 열거하고 구조화하는 또 다른 좋은 이유는 다음과 같습니다.

enum EnumDef
{
  FIRST_ITEM,
  SECOND_ITEM
};

struct StructDef
{
  enum EnuumDef MyEnum;
  unsigned int MyVar;
} MyStruct;

구조체 (Enu u mDef) 에서 EnumDef의 오타에 주목하십시오 . 이것은 오류 (또는 경고)없이 컴파일되며 (C 표준의 리터럴 해석에 따라 다름) 정확합니다. 문제는 방금 내 구조체 내에 새로운 (빈) 열거 정의를 만들었습니다. 이전 정의 EnumDef를 사용하지 않습니다.

typdef를 사용하면 비슷한 종류의 오타가 알려지지 않은 유형을 사용할 때 컴파일러 오류가 발생합니다.

typedef 
{
  FIRST_ITEM,
  SECOND_ITEM
} EnumDef;

typedef struct
{
  EnuumDef MyEnum; /* compiler error (unknown type) */
  unsigned int MyVar;
} StructDef;
StrructDef MyStruct; /* compiler error (unknown type) */

나는 항상 typedef'ing 구조체와 열거를 옹호합니다.

일부 타이핑을 저장하는 것뿐만 아니라 (pun 의도하지 않음;) 더 안전하기 때문입니다.


1
더 나쁜 것은 오타가 다른 태그와 일치 할 수 있습니다. 구조체의 경우 전체 프로그램이 올바르게 컴파일되고 런타임 정의되지 않은 동작이 발생할 수 있습니다.
MM

3
이 정의 : 'typedef {FIRST_ITEM, SECOND_ITEM} EnumDef;' 열거 형을 정의하지 않습니다. 수백 개의 거대한 프로그램을 작성했으며 다른 사람들이 작성한 프로그램에 대한 유지 관리를 수행하는 데 불행이있었습니다. 어려운 경험으로 인해 구조체에서 typedef를 사용하면 문제가 발생합니다. 프로그래머가 너무 장애가 없어서 구조체 인스턴스를 선언 할 때 전체 정의를 입력하는 데 문제가 있기를 바랍니다. C는 기본이 아니므로 더 많은 문자를 입력해도 프로그램 작동에 해롭지 않습니다.
user3629249

2
절대적인 최소 문자 수 이상을 입력하는 것이 싫은 사람들을 위해, 최소한의 키 입력으로 응용 프로그램을 작성하려고 시도하는 일부 그룹에 참여하는 것이 좋습니다. 작업 환경, 특히 동료 검토를 엄격하게 수행하는 작업 환경에서는 새로운 '기술'을 사용하지 마십시오.
user3629249

enum많은 컴파일러가 '잘못된'사용시 이상한 경고를 표시하므로 일반적으로 유형 으로 사용하지 않는 것이 좋습니다 . 예를 들어, enum0을 초기화하면 '정수 상수가 열거 형이 아님'경고가 표시 될 수 있습니다. 를 선언하는 enum것도 허용되지 않습니다. 대신 int(또는 unsigned int)를 사용해야 합니다.
yyny

5
이 예제는 컴파일되지 않으며 예상하지도 않습니다. Debug / test.o test.c : 10 : 17 컴파일 : 오류 : 필드에 'enum EnuumDef'형식이 불완전합니다. enum EnuumDef MyEnum; ^ test.c : 10 : 8 : 참고 : 'enum EnuumDef'의 전방 선언 enum EnuumDef MyEnum; ^ 1 오류가 발생했습니다. gnuc, std = c99.
natersoz

30

Linux 커널 코딩 스타일 5 장에서는을 사용하는 장단점을 제공 typedef합니다.

"vps_t"와 같은 것을 사용하지 마십시오.

구조체와 포인터에 typedef를 사용 하는 것은 실수 입니다. 당신이 볼 때

vps_t a;

출처에서 무엇을 의미합니까?

반대로 말하면

struct virtual_container *a;

실제로 "a"가 무엇인지 알 수 있습니다.

많은 사람들이 typedef가 "가독성을 돕는다"고 생각합니다. 별로. 그들은 다음에 대해서만 유용합니다 :

(a) 완전히 불투명 한 객체 (typedef가 적극적으로 사용되어 객체 를 숨기는 경우)

예 : "pte_t"등 올바른 접근 자 기능을 사용해서 만 액세스 할 수있는 불투명 객체.

노트! 불투명도와 "접근 자 기능"자체는 좋지 않습니다. 우리가 pte_t 등과 같은 것들에 대한 그 (것)들이 그 이유는 정말 절대적 있다는 것입니다 제로 이식 접근 가능한 정보가.

(b) 명확한 정수 유형. 추상화 가 "int"또는 "long"인지 혼동 피하는 데 도움이됩니다 .

u8 / u16 / u32는 여기보다 카테고리 (d)에 더 잘 맞지만 완벽하게 훌륭한 typedef입니다.

노트! 다시 말하지만 이것에 대한 이유가 필요합니다. "부인되지 않은"항목이 있으면 할 이유가 없습니다

typedef unsigned long myflags_t;

그러나 특정 상황에서 "부호없는 int"이고 다른 구성에서 "부호없는 long"인 이유가 분명한 경우, 반드시 typedef를 사용하십시오.

(c) 스파 스를 사용하여 문자 검사를위한 새로운 유형 을 문자 그대로 만들 때 .

(d) 예외적 인 상황에서 표준 C99 유형과 동일한 새로운 유형.

눈과 뇌가 'uint32_t'와 같은 표준 유형에 익숙해지기까지는 짧은 시간이 걸리지 만 일부 사람들은 어쨌든 사용에 반대합니다.

따라서 Linux 고유의 'u8 / u16 / u32 / u64'유형 및 표준 유형과 동일한 서명 된 동등한 유형은 허용되지만 새 코드에서는 필수는 아닙니다.

이미 하나 또는 다른 유형의 세트를 사용하는 기존 코드를 편집 할 때는 해당 코드의 기존 선택 사항을 준수해야합니다.

(e) 사용자 공간에서 사용하기에 안전한 유형.

사용자 공간에 보이는 특정 구조에서는 C99 유형을 요구할 수 없으며 위의 'u32'형식을 사용할 수 없습니다. 따라서 사용자 공간과 공유되는 모든 구조에서 __u32 및 유사한 유형을 사용합니다.

다른 경우도있을 수 있지만 규칙 중 하나를 명확하게 일치시킬 수 없으면 기본적으로 typedef를 절대로 사용해서는 안됩니다.

일반적으로 직접 액세스 할 수있는 요소가있는 포인터 또는 구조체 는 typedef 가 아니 어야합니다 .


4
'불투명도 및 접근 자 기능 자체는 좋지 않습니다.' 누군가 이유를 설명 할 수 있습니까? 정보를 숨기고 캡슐화하는 것이 좋은 생각이라고 생각합니다.
Yawar

5
@ Yawar 방금이 문서를 읽었으며 정확히 같은 생각을 가졌습니다. 물론 C는 객체 지향적이지 않지만 추상화는 여전히 사물입니다.
Baldrickk 2012 년

12

찬반 양론이 있음이 밝혀졌습니다. 유용한 정보 소스는 "Expert C Programming"( 3 장 ) 의 주요 저서 입니다. 간단히 말해 C에는 태그, 유형, 멤버 이름 및 식별자와 같은 여러 네임 스페이스가 있습니다 . typedef유형의 별칭을 도입하고 태그 네임 스페이스에서 찾습니다. 즉,

typedef struct Tag{
...members...
}Type;

두 가지를 정의합니다. 태그 네임 스페이스에 하나의 태그가 있고 유형 네임 스페이스에 하나의 유형이 있습니다. 그래서 당신은 둘 다 할 수 있습니다 Type myTypestruct Tag myTagType. 선언은 유사 struct Type myType하거나 Tag myTagType불법입니다. 또한 다음과 같은 선언에서 :

typedef Type *Type_ptr;

Type에 대한 포인터를 정의합니다. 우리가 선언하면 :

Type_ptr var1, var2;
struct Tag *myTagType1, myTagType2;

다음 var1, var2myTagType1입력 만하는 포인터 myTagType2하지 않음.

위에서 언급 한 책에서, typedefing structs는 프로그래머가 struct라는 단어를 쓰는 것을 막기 때문에 그다지 유용하지 않다고 언급합니다. 그러나 다른 많은 C 프로그래머와 마찬가지로 반대 의견이 있습니다. C에서 다형성을 구현하고 싶을 때 일부 이름을 난독 화하기도하지만 (커널과 같은 큰 코드베이스에서는 권장하지 않는 이유 입니다) 자세한 내용은 여기를 참조하십시오 . 예:

typedef struct MyWriter_t{
    MyPipe super;
    MyQueue relative;
    uint32_t flags;
...
}MyWriter;

넌 할 수있어:

void my_writer_func(MyPipe *s)
{
    MyWriter *self = (MyWriter *) s;
    uint32_t myFlags = self->flags;
...
}

따라서 캐스팅을 통해 flags내부 구조체 ( MyPipe) 로 외부 멤버 ( )에 액세스 할 수 있습니다 . 나를 (struct MyWriter_ *) s;위해 그러한 기능을 수행 할 때마다 전체 유형을 캐스팅하는 것이 혼란스럽지 않습니다. 이러한 경우, 짧은 참조는 특히 코드에서이 기술을 많이 사용하는 경우 큰 문제입니다.

마지막으로, typedefed 유형 의 마지막 측면 은 매크로와 달리 유형을 확장 할 수 없다는 것입니다. 예를 들어 다음이있는 경우

#define X char[10] or
typedef char Y[10]

그런 다음 선언 할 수 있습니다

unsigned X x; but not
unsigned Y y;

스토리지 지정자 ( volatileconst) 에는 적용되지 않으므로 구조체에 대해서는 실제로 신경 쓰지 않습니다 .


1
MyPipe *s; MyWriter *self = (MyWriter *) s;엄격한 앨리어싱을 깨뜨 렸습니다.
Jonathon Reinhart 2018 년

@JonathonReinhart 어떻게 피할 수 있는지, 예를 들어 엄청나게 행복한 GTK +가 어떻게 작동하는지 설명하는 것이 예시 적입니다 : bugzilla.gnome.org/show_bug.cgi?id=140722 / mail.gnome.org/archives/gtk -devel-list / 2004-April / msg00196.html
underscore_d

"typedef는 타입에 대한 별칭을 소개하고 태그 네임 스페이스에서 찾습니다. typedef struct Tag{ ...members... }Type; "두 가지를 정의합니다 "는 의미가 없습니다. typedef가 태그를 정의하면 여기서 'Type'도 태그 여야합니다. 진실은 (. 확인 또는 2 개 유형 1 개 태그 없음) 정의 2 개 태그와 1 개 유형을 정의이다 struct Tag, Tag하고 Type. struct Tag확실히 유형입니다. Tag태그입니다. 그러나 혼란은 Type태그인지 유형인지
Qwertyzw

12

나는 typedef로 순방향 선언이 가능하다고 생각하지 않습니다. struct, enum 및 union을 사용하면 종속성 (알고 있음)이 양방향 일 때 선언을 전달할 수 있습니다.

스타일 : C ++에서 typedef를 사용하는 것은 상당히 의미가 있습니다. 여러 매개 변수 및 / 또는 가변 매개 변수가 필요한 템플릿을 처리 할 때 거의 필요할 수 있습니다. typedef는 이름을 똑바로 유지하는 데 도움이됩니다.

C 프로그래밍 언어에서는 그렇지 않다. typedef의 사용은 대부분 데이터 구조 사용을 난독 화하는 것 외에는 목적이 없습니다. 데이터 유형을 선언하는 데 {struct (6), enum (4), union (5)} 수의 키 입력 만 사용되므로 struct의 별칭 지정에는 거의 사용되지 않습니다. 해당 데이터 형식이 공용체입니까 아니면 구조체입니까? 직접 정의되지 않은 간단한 선언을 사용하면 어떤 유형인지 즉시 알 수 있습니다.

이 별칭이 아닌 넌센스 typedef를 엄격히 피하면서 Linux를 작성하는 방법에 주목하십시오. 결과는 미니멀하고 깔끔한 스타일입니다.


10
깨끗한 struct곳은 어디에서나 반복되지 않을 것입니다 ... Typedef는 새로운 유형을 만듭니다. 무엇을 사용하십니까? 유형. 구조체, 공용체 또는 열거 형인지 상관 하지 않으므로 typedef입니다.
GManNickG

13
아니요, 우리 구조체 또는 공용 체인지 또는 열거 형 또는 원자 유형인지 상관합니다. 구조체를 정수 또는 포인터 (또는 그 문제에 대한 다른 유형)로 강요 할 수 없으며 때로는 컨텍스트를 저장해야합니다. 'struct'또는 'union'키워드를 사용하면 추론의 지역성이 향상됩니다. 아무도 당신 이 구조체 안에 무엇이 있는지 알아야한다고 말합니다 .
Bernd Jendrissek

1
@ BerndJendrissek : Structs와 union은 다른 유형과 다르지만 클라이언트 코드는 두 가지 (struct 또는 union)와 같은 것이 무엇인지 신경 써야 FILE합니까?
supercat

4
@supercat FILE은 typedef를 잘 사용합니다. 나는 typedef가 과도하게 사용 되었다고 생각합니다 . 언어의 오해가 아닙니다. 모든 것에 typedef를 사용하는 IMHO는 "투기 과장 성"코드 냄새입니다. 변수를 FILE * foo로 선언하고 FILE foo로 선언하지 마십시오. 나에게 이것은 중요하다.
Bernd Jendrissek

2
@supercat : "파일 식별 변수가 FILE *가 아닌 FILE 유형 인 경우 ..."그러나 typedef가 가능하게하는 모호성입니다! 우리는 방금 FILE을 가져 와서 열광적으로 사용했습니다. 그래서 우리는 그것에 대해 걱정하지 않지만 typedef를 추가 할 때마다 또 다른인지 적 오버 헤드를 도입하고 있습니다.이 API는 foo_t args 또는 foo_t *를 원합니까? 함수 정의당 문자 수가 몇 개인 경우 '구조'를 명시 적으로 전달하면 추론의 지역성이 향상됩니다.
Bernd Jendrissek

4

기본부터 시작해 보도록하겠습니다.

다음은 구조 정의의 예입니다.

struct point
  {
    int x, y;
  };

여기서 이름 point은 선택 사항입니다.

구조는 정의 중 또는 이후에 선언 될 수 있습니다.

정의 중 선언

struct point
  {
    int x, y;
  } first_point, second_point;

정의 후 선언

struct point
  {
    int x, y;
  };
struct point first_point, second_point;

위의 마지막 경우를주의해서 살펴보십시오. 당신은 쓸 필요가 struct point당신은 당신의 코드에서 나중에에서 그 유형을 만들 것을 결정하는 경우에 해당 유형의 구조를 선언 할 수 있습니다.

를 입력하십시오 typedef. 동일한 블루 프린트를 사용하여 프로그램에서 나중에 새 구조 (구조는 사용자 정의 데이터 유형)를 작성하려는 경우, typedef정의 중에 사용 하면 일부 입력을 저장할 수 있으므로 좋은 아이디어가 될 수 있습니다.

typedef struct point
  {
    int x, y;
  } Points;

Points first_point, second_point;

사용자 정의 유형의 이름을 지정할 때주의 할 사항

사용자 정의 유형 이름 끝에 _t 접미사를 사용하는 것을 막을 수있는 것은 없지만 POSIX 표준은 표준 라이브러리 유형 이름을 나타 내기 위해 접미사 _t를 사용합니다.


3

구조체에 부여한 이름 (선택 사항)을 태그 이름 이라고하며 이미 언급했듯이 그 자체가 유형이 아닙니다. 유형에 도달하려면 구조체 접두사가 필요합니다.

GTK +를 제외하고는 태그 이름이 구조체 유형에 대한 typedef만큼 일반적으로 사용되는지 확실하지 않으므로 C ++에서 인식되며 struct 키워드를 생략하고 태그 이름을 유형 이름으로도 사용할 수 있습니다.


    struct MyStruct
    {
      int i;
    };

    // The following is legal in C++:
    MyStruct obj;
    obj.i = 7;


1

typedef는 상호 의존적 인 데이터 구조 세트를 제공하지 않습니다. 이것은 typdef로는 할 수 없습니다 :

struct bar;
struct foo;

struct foo {
    struct bar *b;
};

struct bar {
    struct foo *f;
};

물론 다음을 추가 할 수 있습니다.

typedef struct foo foo_t;
typedef struct bar bar_t;

정확히 요점은 무엇입니까?


1

A> typdef 는 데이터 유형에 대해보다 의미있는 동의어를 만들 수 있도록하여 프로그램의 의미와 문서화를 도와줍니다 . 또한 이식성 문제 (K & R, pg147, C 프로그램 언어)에 대해 프로그램을 매개 변수화하는 데 도움이됩니다.

B> 구조는 유형을 정의합니다 . Structs는 단일 유닛으로 취급 편의성 (K & R, pg127, C 프로그램 언어)을 위해 var 모음을 편리하게 그룹화 할 수 있습니다.

C> 구조체 정의 typedef에 대해서는 위의 A에서 설명합니다.

D> 나에게 구조체는 사용자 정의 유형 또는 컨테이너 또는 컬렉션 또는 네임 스페이스 또는 복잡한 유형이지만 typdef는 더 많은 별명을 만드는 수단 일뿐입니다.


0

C99 typedef가 필요합니다. 오래되었지만 많은 도구 (ala HackRank)는 c99를 순수한 C 구현으로 사용합니다. 그리고 거기에는 typedef가 필요합니다.

요구 사항이 변경되면 사이트를 인터뷰하는 사람들이 SOL이 될 경우 변경해야한다고 말하고 있지 않습니다 (두 가지 C 옵션이있을 수 있음).


2
"C99에서 기절 typedef해야합니다." 무슨 소리 야?
Julien Lopez

문제는 C아닙니다 C++. 에서 C의 typedef는 '필요'(가장 가능성이 항상있을 것입니다). 에서와 같이 '필수'는 변수를 선언 할 수 없으며 Point varName;유형이 struct Point;없는없이 동의어가 될 수 typedef struct Point Point;있습니다.
yyny

0

'C'프로그래밍 언어에서 키워드 'typedef'는 일부 객체 (struct, array, function..enum type)의 새 이름을 선언하는 데 사용됩니다. 예를 들어 'struct-s'를 사용합니다. 'C'에서 우리는 종종 'main'함수 밖에서 'struct'를 선언합니다. 예를 들면 다음과 같습니다.

struct complex{ int real_part, img_part }COMPLEX;

main(){

 struct KOMPLEKS number; // number type is now a struct type
 number.real_part = 3;
 number.img_part = -1;
 printf("Number: %d.%d i \n",number.real_part, number.img_part);

}

구조체 유형을 사용하기로 결정할 때 마다이 키워드 'struct'something ''name '.'typedef '가 필요합니다. typedef는 단순히 해당 유형의 이름을 바꾸고 원하는 때마다 프로그램에서 새 이름을 사용할 수 있습니다. 따라서 코드는 다음과 같습니다.

typedef struct complex{int real_part, img_part; }COMPLEX;
//now COMPLEX is the new name for this structure and if I want to use it without
// a keyword like in the first example 'struct complex number'.

main(){

COMPLEX number; // number is now the same type as in the first example
number.real_part = 1;
number.img)part = 5;
printf("%d %d \n", number.real_part, number.img_part);

}

전체 프로그램에서 사용될 로컬 객체 (struct, array, 소중한)가 있다면 'typedef'를 사용하여 간단히 이름을 지정할 수 있습니다.


-2

C 언어에서 struct / union / enum은 C 언어 전처리기에 의해 처리되는 매크로 명령입니다 ( "#include"및 기타를 처리하는 전처리 기와 실수하지 마십시오)

그래서 :

struct a
{
   int i;
};

struct b
{
   struct a;
   int i;
   int j;
};

struct b는 다음과 같이 소비됩니다.

struct b
{
    struct a
    {
        int i;
    };
    int i;
    int j;
}

따라서 컴파일 타임에 스택에서 다음과 같이 진화합니다. b : int ai int i int j

그것은 또한 자기 참조 구조를 갖는 것이 어려운 이유입니다. C 전처리 기는 종료 할 수없는 선언 루프에서 둥글게됩니다.

typedef는 형식 지정자이므로 C 컴파일러 만 처리하고 처리기 코드 구현을 최적화하려는 것처럼 할 수 있습니다. 또한 pprocessor가 구조체를 사용하는 것처럼 어리석게 par 유형의 멤버를 소비하지 않지만보다 복잡한 참조 구성 알고리즘을 사용하므로 다음과 같이 구성됩니다.

typedef struct a A; //anticipated declaration for member declaration

typedef struct a //Implemented declaration
{
    A* b; // member declaration
}A;

허용되고 완벽하게 작동합니다. 이 구현은 또한 컴파일러 유형 변환에 대한 액세스를 제공하고 실행 스레드가 초기화 함수의 응용 프로그램 필드를 벗어날 때 일부 버그 효과를 제거합니다.

이것은 C typedef가 외로운 구조체보다 C ++ 클래스에 더 가깝다는 것을 의미합니다.


3
자기 참조 구조를 갖는 것은 어렵지 않습니다. struct foo {struct foo * next; INT 일; }
Bernd Jendrissek 18.52에

4
...뭐? 말하는 전처리 의 해상도를 설명 structs하고 typedef이야 것은 나쁜 충분하지만, 당신의 쓰기의 나머지는 내가 열심히 그것에서 어떤 메시지가 찾을 것으로 혼동된다. 그러나 내가 말할 수있는 한 가지는 typedefd struct가 아닌 것을 앞으로 선언하거나 불투명 (포인터) 멤버로 사용할 수 없다는 생각 은 완전히 거짓이라는 것입니다. 당신의 첫번째 예에서, struct b사소를 포함 할 수 있습니다 struct a *, 더는 typedef필요하지 않습니다. 있다는 주장 struct들 매크로 확장 단지 벙어리 조각, 그리고 것을 typedef들, 그들에게 혁신적인 새로운 능력을 부여 고통스럽게 잘못된
underscore_d
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.