문제

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

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

elem user;

왜 그렇게 자주 필요한가요? 특정 이유 또는 해당 지역이 있습니까?

도움이 되었습니까?

해결책

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;
}

전부의 "구조"키워드를 볼 필요가 없을 때 더 깨끗해지면 언어에 "포인트"라는 유형이있는 것처럼 보입니다. 이후 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;
}

후자의 경우, 정의는 헤더 파일 사용자로부터 숨겨져 있기 때문에 값으로 포인트를 반환 할 수 없습니다. 이것은 광범위하게 사용되는 기술입니다 gtk+, 예를 들어.

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

다른 팁

얼마나 많은 사람들이 이것을 잘못했는지 놀랍습니다. C에서 structs를 입력하지 마십시오. 일반적으로 이미 큰 C 프로그램에서 매우 오염 된 글로벌 네임 스페이스를 불필요하게 오염시킵니다.

또한 태그 이름이없는 typedef'd structs는 헤더 파일 간의 순서 관계의 불필요한 부과의 주요 원인입니다.

고려하다:

#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

TypEdefs를 사용하지 않는 이러한 정의를 사용하면 컴파일 랜드 장치에 foo.h를 포함 할 수 있습니다. FOO_DEF 정의. 그것이 '바'멤버의 회의를 시도하지 않으면 foo 구조 그러면 "bar.h"파일을 포함 할 필요가 없습니다.

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

struct foo *foo;

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

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

코드를 유지 해야하는 경우 typedef'd structs를 제거합니다.

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;

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

많은 프로그래머 (당신을 포함하여)는 구조물 이름을 유형 이름으로 생각하는 것을 선호하므로 typedef를 사용하여 태그의 별칭을 정의합니다. 예를 들어 정의합니다

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

구조물 대신 S를 사용할 수 있습니다.

S x;
S *p;

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

S S;    // error

이것은 좋습니다.

struct, Union 또는 Enum 정의의 태그 이름은 선택 사항입니다. 많은 프로그래머는 구조물 정의를 typedef에 접고 다음과 같이 태그를 완전히 분배합니다.

typedef struct
    {
    ...
    } S;

링크 된 기사는 또한 C ++ 동작이 typedef 미묘한 이름 숨어 문제를 일으킬 수 있습니다. 이러한 문제를 방지하기 위해 typedef C ++의 수업과 구조도 언뜻보기에 불필요한 것으로 보입니다. C ++에서 typedef 숨어있는 이름은 컴파일러가 잠재적 인 문제의 숨겨진 원인이 아니라 당신에게 알려주는 오류가됩니다.

사용 a typedef 글을 쓰지 않아도됩니다 struct 해당 유형의 변수를 선언 할 때마다 다음과 같습니다.

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

열거와 구조를 항상 입력 해야하는 또 다른 좋은 이유는이 문제로 인해 발생합니다.

enum EnumDef
{
  FIRST_ITEM,
  SECOND_ITEM
};

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

구조물의 enumdef에있는 오타를 주목하십시오 (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) */

나는 항상 스트러크와 열거를 입력 할 것입니다.

일부 타이핑을 저장할뿐만 아니라 (말장난 의도가 없음) 더 안전하기 때문입니다.

Linux 커널 코딩 스타일 5 장은 사용에 대한 훌륭한 장단점 (주로 단점)을 제공합니다. typedef.

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

그것은 a입니다 실수 구조 및 포인터에 typedef를 사용합니다. 당신이 볼 때

vps_t a;

소스에서 무엇을 의미합니까?

대조적으로 말하면

struct virtual_container *a;

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

많은 사람들이 Typedefs가 "가독성에 도움이됩니다"라고 생각합니다. 별로. 그들은 다음에만 유용합니다.

(a) 완전히 불투명 한 물체 (typedef가 적극적으로 사용되는 곳 숨다 대상이 무엇인지).

예 : "PTE_T"등의 적절한 액세서 기능을 사용 하여만 액세스 할 수있는 불투명 객체.

노트! 불투명성과 "액세서 기능"은 그 자체로 좋지 않습니다. PTE_T 등과 같은 것들을 위해 우리가 가지고있는 이유는 정말로 절대적으로 편리하게 액세스 할 수있는 정보.

(b) 명확한 정수 유형, 여기서 추상화 도움이됩니다 "int"또는 "long"이든 혼란을 피하십시오.

U8/U16/U32는 여기보다 카테고리 (d)에 더 잘 맞지만 완벽하게 미세한 typedef입니다.

노트! 다시 - a가 필요합니다 이유 이것을 위해. 무언가가 "서명되지 않은"경우, 할 이유가 없습니다.

typedef unsigned long myflags_t;

그러나 특정 상황에서 왜 "서명되지 않은 int"가 될 수 있고 다른 구성에서 "서명되지 않은"이유에 대한 분명한 이유가 있다면, 계속해서 TypEdef를 사용하십시오.

(c) 스파 스를 사용하여 문자 그대로 새로운 유형 확인을위한 유형.

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

눈과 뇌가 'UINT32_T'와 같은 표준 유형에 익숙해지는 데 짧은 시간이 걸리지 만, 어떤 사람들은 어쨌든 자신의 사용에 반대합니다.

따라서 Linux 특이 적 'U8/U16/U32/U64'유형과 표준 유형과 동일한 서명 된 등가물이 허용됩니다. 그러나 새로운 코드는 필수는 아니지만 자신의 새로운 코드는 허용됩니다.

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

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

사용자 공간에 보이는 특정 구조에서는 C99 유형을 요구할 수 없으며 위의 'U32'형태를 사용할 수 없습니다. 따라서 우리는 사용자 공간과 공유되는 모든 구조에서 __U32와 유사한 유형을 사용합니다.

어쩌면 다른 사례도있을 수도 있지만 규칙은 기본적으로 해당 규칙 중 하나를 명확하게 일치 할 수 없다면 타이핑을 사용하지 않아야합니다.

일반적으로 포인터 또는 합리적으로 직접 액세스 할 수있는 요소가있는 구조 절대 typedef가 되십시오.

장단점이 있음이 밝혀졌습니다. 유용한 정보 소스는 중요한 책 "Expert C 프로그래밍"입니다.3 장). 간단히, C에는 여러 개의 네임 스페이스가 있습니다. 태그, 유형, 멤버 이름 및 식별자. typedef 유형에 대한 별칭을 소개하고 태그 네임 스페이스에서 찾습니다. 즉,

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

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

typedef Type *Type_ptr;

우리는 우리 유형에 대한 포인터를 정의합니다. 그래서 우리가 선언한다면 :

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

그 다음에 var1,var2 그리고 myTagType1 입력 할 포인터이지만 myTagType2 아니다.

위에서 언급 한 책에서 Typedefing Structs는 프로그래머가 구조물이라는 단어를 작성하는 것을 저장하기 때문에 유용하지 않다고 언급합니다. 그러나 다른 많은 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;

저장 지정자에게는 적용되지 않기 때문에 Structs에 대해 실제로 신경 쓰지 않습니다.volatile 그리고 const).

나는 TypEdef와 함께 앞으로 선언이 가능하다고 생각하지 않습니다. 구조물, 열거 및 노조의 사용은 종속성 (알고 있음)이 양방향 일 때 선언을 전달할 수 있습니다.

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

C 프로그래밍 언어로는 그렇지 않습니다. TypEdef의 사용은 대부분 데이터 구조 사용을 난독 화하는 것 외에는 목적이 없습니다. {struct (6), enum (4), Union (5)} KeyStrokes 수는 데이터 유형을 선언하는 데 사용되므로 구조물의 별칭을 거의 사용하지 않습니다. 그 데이터 타입 A Union입니까 아니면 구조물입니까? 간단한 비 형성 선언을 사용하면 어떤 유형인지 즉시 알려줍니다.

Linux 가이 별칭의 말도 안되는 말도 안되는 Typedef가 제공하는 방법에 주목하십시오. 결과는 미니멀하고 깨끗한 스타일입니다.

기본부터 시작하여 우리의 길을가 봅시다.

구조 정의의 예는 다음과 같습니다.

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를 사용합니다.

당신이 (선택적으로) 구조물을주는 이름을 태그 이름 그리고 언급 된 바와 같이, 그 자체로는 유형이 아닙니다. 유형에 도달하려면 Struct Prefix가 필요합니다.

GTK+를 제외하고, TagName이 구조물 유형의 유형과 같은 일반적으로 사용되는지 확실하지 않으므로 C ++에서는 인식 된 C ++에서 구조물 키워드를 생략하고 Tagname을 유형 이름으로 사용할 수 있습니다.


    struct MyStruct
    {
      int i;
    };

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

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;

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

a> typdef는 허용하여 프로그램의 의미와 문서화를 지원합니다 데이터 유형에 대한보다 의미있는 동의어 생성. 또한 이식성 문제 (K & R, PG147, C Prog Lang)에 대한 프로그램을 매개 변수화하는 데 도움이됩니다.

b>구조는 유형을 정의합니다. Structs는 단일 장치로서 취급의 편의성 (K & R, PG127, C Prog Lang.)의 편의를 위해 VAR 모음을 편리하게 그룹화 할 수 있습니다.

c> typedef'ing 구조물은 위의 설명에 설명되어 있습니다.

D> 나에게 Structs는 사용자 정의 유형 또는 컨테이너 또는 컬렉션 또는 네임 스페이스 또는 복잡한 유형 인 반면 TypDef는 더 많은 닉네임을 만드는 수단 일뿐입니다.

C99 Typedef에서 밝혀졌습니다. 구식이지만 많은 도구 (ALA Hackrank)는 C99를 순수한 C 구현으로 사용합니다. 그리고 typedef가 필요합니다.

요구 사항이 변경되면 변경해야한다고 말하는 것은 아닙니다 (아마도 두 가지 C 옵션이있을 수 있음). 사이트에서의 인터뷰를 위해 우리의 요구 사항이 Sol 일 것입니다.

'C'프로그래밍 언어에서 키워드 'typedef'는 일부 객체 (struct, array, function..enum 유형)의 새 이름을 선언하는 데 사용됩니다. 예를 들어, 나는 'struct-s'를 사용합니다. 'C'에서는 종종 '기본'기능 외부에서 '구조'를 선언합니다. 예를 들어:

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 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);

}

전체 프로그램에 사용될 로컬 객체 (구조, 배열, 귀중한)가있는 경우 'typedef'를 사용하여 단순히 이름을 줄 수 있습니다.

C 언어에서 구조물/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 컴파일러 프로세스만이 IT를 처리하며 어셈블러 코드 구현을 최적화하려는 것처럼 수행 할 수 있습니다. 또한 Préprocessor와 같은 유형의 PAR 회원은 Structs와 같이 어리석게 소비되지 않지만보다 복잡한 참조 구성 알고리즘을 사용하므로 다음과 같은 구성을 사용합니다.

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

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

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

이는 C typedef가 외로운 구조보다 C ++ 클래스와 더 가까워진다는 것을 의미합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top