아래와 같은 구조로 구성된 많은 프로그램을 보았습니다.
typedef struct
{
int i;
char k;
} elem;
elem user;
왜 그렇게 자주 필요합니까? 특정한 이유나 적용 가능한 영역이 있습니까?
struct * ptr
. 구조체 내부의 줄 이 오류를 일으킬 수 있기 때문입니다
아래와 같은 구조로 구성된 많은 프로그램을 보았습니다.
typedef struct
{
int i;
char k;
} elem;
elem user;
왜 그렇게 자주 필요합니까? 특정한 이유나 적용 가능한 영역이 있습니까?
struct * ptr
. 구조체 내부의 줄 이 오류를 일으킬 수 있기 때문입니다
답변:
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 장을 참조하십시오 . :) 내 요점은 문제의 "반드시"가 아마도 돌로 설정되어 있지 않다는 것입니다.
얼마나 많은 사람들이이 잘못을 저지르는지는 놀랍습니다. 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의 구조체를 제거합니다.
typedef struct X { ... } X
입니다. 이렇게하면 짧은 형식 X
을 사용하여 정의를 사용할 수있는 곳 어디에서나 구조체를 처리 할 수 있지만 struct X
원하는 경우 계속 선언하고 사용할 수 있습니다.
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
에서 이름 숨기기를 사용하면 잠재적 인 문제의 숨겨진 원인이 아니라 컴파일러에서 알려주는 오류가됩니다.
int stat(const char *restrict path, struct stat *restrict buf)
있습니다. 거기에는 stat
일반 네임 스페이스와 struct stat
태그 네임 스페이스에 기능이 있습니다.
사용 typedef
하면 struct
해당 유형의 변수를 선언 할 때마다 쓰지 않아도됩니다 .
struct elem
{
int i;
char k;
};
elem user; // compile error!
struct elem user; // this is correct
typedef
일반적으로 구조를 거부하는 이유는 아닙니다 . 당신은 또한 할 수 있습니다 typedef struct foo foo;
. 물론 struct
키워드는 더 이상 필요하지 않습니다. 우리가 보는 유형 별칭은 구조의 별칭이지만 일반적으로 나쁘지는 않습니다. 결과 유형 별명의 식별자 typedef
가 그것이 구조의 별명 인 fe : 를 나타내는 경우도 고려하십시오 typedef struct foo foo_struct;
.
이 문제의 결과를 항상 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 의도하지 않음;) 더 안전하기 때문입니다.
enum
많은 컴파일러가 '잘못된'사용시 이상한 경고를 표시하므로 일반적으로 유형 으로 사용하지 않는 것이 좋습니다 . 예를 들어, enum
0을 초기화하면 '정수 상수가 열거 형이 아님'경고가 표시 될 수 있습니다. 를 선언하는 enum
것도 허용되지 않습니다. 대신 int
(또는 unsigned int
)를 사용해야 합니다.
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 가 아니 어야합니다 .
찬반 양론이 있음이 밝혀졌습니다. 유용한 정보 소스는 "Expert C Programming"( 3 장 ) 의 주요 저서 입니다. 간단히 말해 C에는 태그, 유형, 멤버 이름 및 식별자와 같은 여러 네임 스페이스가 있습니다 . typedef
유형의 별칭을 도입하고 태그 네임 스페이스에서 찾습니다. 즉,
typedef struct Tag{
...members...
}Type;
두 가지를 정의합니다. 태그 네임 스페이스에 하나의 태그가 있고 유형 네임 스페이스에 하나의 유형이 있습니다. 그래서 당신은 둘 다 할 수 있습니다 Type myType
와 struct Tag myTagType
. 선언은 유사 struct Type myType
하거나 Tag myTagType
불법입니다. 또한 다음과 같은 선언에서 :
typedef Type *Type_ptr;
Type에 대한 포인터를 정의합니다. 우리가 선언하면 :
Type_ptr var1, var2;
struct Tag *myTagType1, myTagType2;
다음 var1
, var2
및 myTagType1
입력 만하는 포인터 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;
위해 그러한 기능을 수행 할 때마다 전체 유형을 캐스팅하는 것이 혼란스럽지 않습니다. 이러한 경우, 짧은 참조는 특히 코드에서이 기술을 많이 사용하는 경우 큰 문제입니다.
마지막으로, typedef
ed 유형 의 마지막 측면 은 매크로와 달리 유형을 확장 할 수 없다는 것입니다. 예를 들어 다음이있는 경우
#define X char[10] or
typedef char Y[10]
그런 다음 선언 할 수 있습니다
unsigned X x; but not
unsigned Y y;
스토리지 지정자 ( volatile
및 const
) 에는 적용되지 않으므로 구조체에 대해서는 실제로 신경 쓰지 않습니다 .
MyPipe *s; MyWriter *self = (MyWriter *) s;
엄격한 앨리어싱을 깨뜨 렸습니다.
typedef struct Tag{ ...members... }Type;
"두 가지를 정의합니다 "는 의미가 없습니다. typedef가 태그를 정의하면 여기서 'Type'도 태그 여야합니다. 진실은 (. 확인 또는 2 개 유형 1 개 태그 없음) 정의 2 개 태그와 1 개 유형을 정의이다 struct Tag
, Tag
하고 Type
. struct Tag
확실히 유형입니다. Tag
태그입니다. 그러나 혼란은 Type
태그인지 유형인지
나는 typedef로 순방향 선언이 가능하다고 생각하지 않습니다. struct, enum 및 union을 사용하면 종속성 (알고 있음)이 양방향 일 때 선언을 전달할 수 있습니다.
스타일 : C ++에서 typedef를 사용하는 것은 상당히 의미가 있습니다. 여러 매개 변수 및 / 또는 가변 매개 변수가 필요한 템플릿을 처리 할 때 거의 필요할 수 있습니다. typedef는 이름을 똑바로 유지하는 데 도움이됩니다.
C 프로그래밍 언어에서는 그렇지 않다. typedef의 사용은 대부분 데이터 구조 사용을 난독 화하는 것 외에는 목적이 없습니다. 데이터 유형을 선언하는 데 {struct (6), enum (4), union (5)} 수의 키 입력 만 사용되므로 struct의 별칭 지정에는 거의 사용되지 않습니다. 해당 데이터 형식이 공용체입니까 아니면 구조체입니까? 직접 정의되지 않은 간단한 선언을 사용하면 어떤 유형인지 즉시 알 수 있습니다.
이 별칭이 아닌 넌센스 typedef를 엄격히 피하면서 Linux를 작성하는 방법에 주목하십시오. 결과는 미니멀하고 깔끔한 스타일입니다.
struct
곳은 어디에서나 반복되지 않을 것입니다 ... Typedef는 새로운 유형을 만듭니다. 무엇을 사용하십니까? 유형. 구조체, 공용체 또는 열거 형인지 상관 하지 않으므로 typedef입니다.
FILE
합니까?
기본부터 시작해 보도록하겠습니다.
다음은 구조 정의의 예입니다.
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를 사용합니다.
구조체에 부여한 이름 (선택 사항)을 태그 이름 이라고하며 이미 언급했듯이 그 자체가 유형이 아닙니다. 유형에 도달하려면 구조체 접두사가 필요합니다.
GTK +를 제외하고는 태그 이름이 구조체 유형에 대한 typedef만큼 일반적으로 사용되는지 확실하지 않으므로 C ++에서 인식되며 struct 키워드를 생략하고 태그 이름을 유형 이름으로도 사용할 수 있습니다.
struct MyStruct
{
int i;
};
// The following is legal in C++:
MyStruct obj;
obj.i = 7;
A> typdef 는 데이터 유형에 대해보다 의미있는 동의어를 만들 수 있도록하여 프로그램의 의미와 문서화를 도와줍니다 . 또한 이식성 문제 (K & R, pg147, C 프로그램 언어)에 대해 프로그램을 매개 변수화하는 데 도움이됩니다.
B> 구조는 유형을 정의합니다 . Structs는 단일 유닛으로 취급 편의성 (K & R, pg127, C 프로그램 언어)을 위해 var 모음을 편리하게 그룹화 할 수 있습니다.
C> 구조체 정의 typedef에 대해서는 위의 A에서 설명합니다.
D> 나에게 구조체는 사용자 정의 유형 또는 컨테이너 또는 컬렉션 또는 네임 스페이스 또는 복잡한 유형이지만 typdef는 더 많은 별명을 만드는 수단 일뿐입니다.
C99 typedef가 필요합니다. 오래되었지만 많은 도구 (ala HackRank)는 c99를 순수한 C 구현으로 사용합니다. 그리고 거기에는 typedef가 필요합니다.
요구 사항이 변경되면 사이트를 인터뷰하는 사람들이 SOL이 될 경우 변경해야한다고 말하고 있지 않습니다 (두 가지 C 옵션이있을 수 있음).
typedef
해야합니다." 무슨 소리 야?
C
아닙니다 C++
. 에서 C
의 typedef는 '필요'(가장 가능성이 항상있을 것입니다). 에서와 같이 '필수'는 변수를 선언 할 수 없으며 Point varName;
유형이 struct Point;
없는없이 동의어가 될 수 typedef struct Point Point;
있습니다.
'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'를 사용하여 간단히 이름을 지정할 수 있습니다.
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 ++ 클래스에 더 가깝다는 것을 의미합니다.
structs
하고 typedef
이야 것은 나쁜 충분하지만, 당신의 쓰기의 나머지는 내가 열심히 그것에서 어떤 메시지가 찾을 것으로 혼동된다. 그러나 내가 말할 수있는 한 가지는 typedef
d struct
가 아닌 것을 앞으로 선언하거나 불투명 (포인터) 멤버로 사용할 수 없다는 생각 은 완전히 거짓이라는 것입니다. 당신의 첫번째 예에서, struct b
사소를 포함 할 수 있습니다 struct a *
, 더는 typedef
필요하지 않습니다. 있다는 주장 struct
들 매크로 확장 단지 벙어리 조각, 그리고 것을 typedef
들, 그들에게 혁신적인 새로운 능력을 부여 고통스럽게 잘못된