ฉันได้เห็นหลายโปรแกรมที่ประกอบด้วยโครงสร้างเช่นเดียวกับด้านล่าง
typedef struct
{
int i;
char k;
} elem;
elem user;
ทำไมมันจำเป็นบ่อยครั้ง เหตุผลเฉพาะหรือพื้นที่ที่บังคับใช้?
struct * ptr
ภายในโครงสร้างจะทำให้เกิดข้อผิดพลาด
ฉันได้เห็นหลายโปรแกรมที่ประกอบด้วยโครงสร้างเช่นเดียวกับด้านล่าง
typedef struct
{
int i;
char k;
} elem;
elem user;
ทำไมมันจำเป็นบ่อยครั้ง เหตุผลเฉพาะหรือพื้นที่ที่บังคับใช้?
struct * ptr
ภายในโครงสร้างจะทำให้เกิดข้อผิดพลาด
คำตอบ:
ที่เกร็ก Hewgill กล่าวว่า typedef หมายความว่าคุณไม่ต้องเขียนstruct
ทั่วทุกสถานที่ ซึ่งไม่เพียงบันทึกการกดแป้นพิมพ์เท่านั้น แต่ยังสามารถสร้างรหัสที่สะอาดขึ้นอีกด้วย
สิ่งที่ชอบ
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 ตามเนื่องจากคำจำกัดความถูกซ่อนจากผู้ใช้ไฟล์ส่วนหัว นี่เป็นเทคนิคที่ใช้กันอย่างแพร่หลายในGTK +เป็นต้น
อัพเดตโปรดทราบว่านอกจากนี้ยังมีโครงการ C ที่ได้รับการยอมรับอย่างสูงซึ่งการใช้typedef
เพื่อซ่อนstruct
นี้ถือเป็นความคิดที่ไม่ดีเคอร์เนล Linux น่าจะเป็นโครงการที่รู้จักกันดีที่สุด ดูบทที่ 5 ของเอกสาร Linux Kernel CodingStyleสำหรับคำพูดที่ทำให้โกรธของ Linus :) จุดของฉันคือว่า "ควร" ในคำถามอาจไม่ได้ตั้งอยู่ในหินหลังจากทั้งหมด
เป็นเรื่องที่น่าอัศจรรย์ว่ามีคนกี่คนที่ทำสิ่งนี้ผิด โปรดอย่าพิมพ์ structsef ใน C โดยไม่จำเป็นต้องสร้างมลภาวะเนมสเปซส่วนกลางซึ่งโดยทั่วไปแล้วจะมีมลพิษมากในโปรแกรม 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
คำจำกัดความ หากไม่พยายามยกเลิกการลงทะเบียนสมาชิก 'bar' ของfoo
struct คุณไม่จำเป็นต้องรวมไฟล์ "bar.h"
นอกจากนี้เนื่องจากเนมสเปซมีความแตกต่างระหว่างชื่อแท็กและชื่อสมาชิกจึงเป็นไปได้ที่จะเขียนโค้ดที่อ่านได้มากเช่น:
struct foo *foo;
printf("foo->bar = %p", foo->bar);
เนื่องจากเนมสเปซนั้นแยกจากกันจึงไม่มีความขัดแย้งในการตั้งชื่อตัวแปรที่ตรงกับชื่อแท็ก struct
ถ้าฉันต้องรักษารหัสของคุณฉันจะลบ structeded typedef ของคุณ
typedef struct X { ... } X
รูปแบบที่ปลอดภัยคือการใช้งาน ด้วยวิธีนี้คุณสามารถใช้รูปแบบย่อX
เพื่อกำหนดโครงสร้างได้ทุกที่ที่มีคำจำกัดความ แต่ยังสามารถประกาศล่วงหน้าและใช้struct X
เมื่อต้องการ
จากบทความเก่าโดย Dan Saks ( http://www.ddj.com/cpp/184403396?pgno=3 ):
กฎภาษา C สำหรับการตั้งชื่อ structs นั้นผิดปกติเล็กน้อย แต่ก็ไม่เป็นอันตรายเลย อย่างไรก็ตามเมื่อขยายไปยังคลาสใน 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;
เป็นการประกาศที่ถูกต้องซึ่งประกาศตัวแปร s ของ type struct s มันอาจไม่ใช่วิธีปฏิบัติที่ดี แต่คอมไพเลอร์ C ต้องยอมรับมัน ฉันไม่เคยเห็นเหตุผลว่าทำไม C จึงได้รับการออกแบบด้วยวิธีนี้ ฉันคิดเสมอว่ามันเป็นความผิดพลาด แต่ก็มี
โปรแกรมเมอร์หลายคน (รวมถึงของคุณอย่างแท้จริง) ชอบคิดชื่อ struct เป็นชื่อประเภทดังนั้นพวกเขาจึงกำหนดนามแฝงสำหรับแท็กโดยใช้ typedef ตัวอย่างเช่นการกำหนด
struct s { ... }; typedef struct s S;
ให้คุณใช้ S แทน struct s เช่นเดียวกับใน
S x; S *p;
โปรแกรมไม่สามารถใช้ S เป็นชื่อของทั้งสองประเภทและตัวแปร (หรือฟังก์ชั่นหรือค่าคงที่การแจงนับ):
S S; // error
ดีจัง.
ชื่อแท็กในนิยาม struct, union หรือ enum เป็นทางเลือก โปรแกรมเมอร์หลายคนพับนิยาม struct ลงใน typedef และแจกจ่ายด้วยแท็กโดยสิ้นเชิงดังที่:
typedef struct { ... } S;
บทความที่เชื่อมโยงยังมีการอภิปรายเกี่ยวกับวิธีการทำงานของ C ++ ที่ไม่ต้องการการใช้typedef
อาจทำให้เกิดปัญหาการซ่อนชื่อที่ละเอียด เพื่อป้องกันปัญหาเหล่านี้เป็นความคิดที่ดีสำหรับtypedef
คลาสและโครงสร้างของคุณใน C ++ เช่นกันแม้ว่าจะเห็นได้อย่างรวดเร็วก่อนว่ามันไม่จำเป็น ใน C ++ ด้วยการtypedef
ซ่อนชื่อกลายเป็นข้อผิดพลาดที่คอมไพเลอร์บอกคุณเกี่ยวกับแทนที่จะเป็นแหล่งซ่อนเร้นของปัญหาที่อาจเกิดขึ้น
int stat(const char *restrict path, struct stat *restrict buf)
ฟังก์ชัน ที่นั่นคุณมีฟังก์ชั่นstat
ในพื้นที่ชื่อสามัญและstruct stat
ในพื้นที่ชื่อแท็ก
การใช้typedef
avoids ต้องเขียนstruct
ทุกครั้งที่คุณประกาศตัวแปรประเภทนั้น:
struct elem
{
int i;
char k;
};
elem user; // compile error!
struct elem user; // this is correct
typedef
โครงสร้างไอเอ็นจีโดยทั่วไป typedef struct foo foo;
นอกจากนี้คุณยังสามารถทำ แน่นอนว่าstruct
คำหลักนั้นไม่จำเป็นต้องมากกว่านั้นซึ่งอาจเป็นคำใบ้ที่มีประโยชน์ว่านามแฝงประเภทที่เราดูเป็นนามแฝงสำหรับโครงสร้าง แต่มันก็ไม่ได้เลวร้ายโดยทั่วไป ยังพิจารณากรณีที่ระบุของนามแฝงประเภทส่งผลให้การtypedef
แสดงให้เห็นว่ามันเป็นนามแฝงสำหรับโครงสร้าง typedef struct foo foo_struct;
fe:
อีกหนึ่งเหตุผลที่ดีในการพิมพ์ enums และ structs เป็นผลมาจากปัญหานี้:
enum EnumDef
{
FIRST_ITEM,
SECOND_ITEM
};
struct StructDef
{
enum EnuumDef MyEnum;
unsigned int MyVar;
} MyStruct;
สังเกตเห็นการพิมพ์ผิดใน EnumDef ใน struct (Enu u mDef)? สิ่งนี้รวบรวมโดยไม่มีข้อผิดพลาด (หรือคำเตือน) และเป็น (ขึ้นอยู่กับการตีความตามตัวอักษรของมาตรฐาน 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) */
ฉันจะสนับสนุนให้พิมพ์คำสั่งและการแจกแจงตลอดเวลา
ไม่เพียง แต่จะบันทึกการพิมพ์บางส่วน (ไม่ได้ตั้งใจเล่นสำนวน)) แต่เพราะมันปลอดภัยกว่า
enum
เป็นประเภทเพราะคอมไพเลอร์จำนวนมากปล่อยคำเตือนแปลก ๆ เมื่อใช้ 'ผิด' ตัวอย่างเช่นการเริ่มต้นenum
ถึง 0 อาจให้คำเตือน 'จำนวนเต็มคงที่ไม่ได้อยู่ใน enum' เตือน enum
ไม่อนุญาตให้ส่งต่อการประกาศไปข้างหน้า ควรใช้int
(หรือunsigned int
) แทน
สไตล์ลินุกซ์เคอร์เนลการเข้ารหัสบทที่ 5 ให้ดีข้อดีและข้อเสีย (ส่วนใหญ่ข้อเสีย) typedef
ของการใช้
โปรดอย่าใช้สิ่งต่าง ๆ เช่น "vps_t"
มันเป็น ความผิดพลาดในการใช้ typedef สำหรับโครงสร้างและพอยน์เตอร์ เมื่อคุณเห็น
vps_t a;
ในแหล่งข้อมูลมันหมายความว่าอย่างไร
ในทางตรงกันข้ามถ้ามันบอกว่า
struct virtual_container *a;
คุณสามารถบอกได้ว่า "a" คืออะไร
ผู้คนจำนวนมากคิดว่าคำว่า "ช่วยให้อ่านง่าย" ไม่เช่นนั้น มีประโยชน์สำหรับ:
(a) วัตถุทึบแสงทั้งหมด (ที่ typedef ใช้อย่างแข็งขันเพื่อซ่อนสิ่งที่เป็น)
ตัวอย่าง: "pte_t" ฯลฯ วัตถุทึบแสงที่คุณสามารถเข้าถึงได้โดยใช้ฟังก์ชั่นอุปกรณ์เสริมที่เหมาะสมเท่านั้น
บันทึก! ความทึบและ "ฟังก์ชั่นการเข้าถึง" ไม่ดีในตัวเอง เหตุผลที่เรามีพวกเขาสำหรับสิ่งต่าง ๆ เช่น pte_t เป็นต้นนั่นคือไม่มีข้อมูลที่สามารถเข้าถึงได้ที่นี่
(b) Clear จำนวนเต็มชนิดซึ่งสิ่งที่เป็นนามธรรมช่วยหลีกเลี่ยงความสับสนไม่ว่าจะเป็น "int" หรือ "long"
u8 / u16 / u32 นั้นเป็นตัวพิมพ์ดีดที่สมบูรณ์แบบแม้ว่ามันจะอยู่ในหมวดหมู่ (d) ดีกว่าที่นี่
บันทึก! อีกครั้ง - จะต้องมีเหตุผลสำหรับสิ่งนี้ หากสิ่งที่ "ไม่ได้ลงนามนาน" แล้วไม่มีเหตุผลที่จะทำ
typedef unsigned long myflags_t;
แต่ถ้ามีเหตุผลที่ชัดเจนว่าทำไมภายใต้สถานการณ์บางอย่างอาจเป็น "int ไม่ได้ลงนาม" และภายใต้การกำหนดค่าอื่น ๆ อาจจะ "ไม่ได้ลงนามยาว" แล้วโดยวิธีทั้งหมดไปข้างหน้าและใช้ typedef
(c) เมื่อคุณใช้ sparse เพื่อสร้าง a ชนิดใหม่สำหรับการตรวจสอบชนิด
(d) ประเภทใหม่ที่เหมือนกันกับประเภท C99 มาตรฐานในสถานการณ์พิเศษบางอย่าง
แม้ว่าจะใช้เวลาเพียงระยะเวลาสั้น ๆ เท่านั้นที่ตาและสมองจะคุ้นเคยกับประเภทมาตรฐานเช่น 'uint32_t' บางคนคัดค้านการใช้งานของพวกเขาอย่างไรก็ตาม
ดังนั้นประเภทเฉพาะ 'u8 / u16 / u32 / u64' ของ Linux และรายการเทียบเท่าที่ลงนามซึ่งเหมือนกันกับประเภทมาตรฐานจะได้รับอนุญาต - แม้ว่าจะไม่บังคับในรหัสใหม่ของคุณเอง
เมื่อแก้ไขรหัสที่มีอยู่ซึ่งใช้หนึ่งหรือประเภทชุดอื่นคุณควรปฏิบัติตามตัวเลือกที่มีอยู่ในรหัสนั้น
(e) ประเภทปลอดภัยสำหรับใช้ใน userspace
ในโครงสร้างบางอย่างที่ผู้ใช้สามารถมองเห็นได้เราไม่สามารถต้องการชนิด C99 และไม่สามารถใช้แบบฟอร์ม 'u32' ด้านบน ดังนั้นเราจึงใช้ __u32 และประเภทที่คล้ายกันในโครงสร้างทั้งหมดซึ่งแชร์กับ userspace
อาจมีกรณีอื่นด้วยเช่นกัน แต่โดยทั่วไปแล้วกฎไม่ควรใช้ typedef เว้นแต่คุณจะสามารถจับคู่กฎข้อใดข้อหนึ่งได้อย่างชัดเจน
โดยทั่วไปตัวชี้หรือ struct ที่มีองค์ประกอบที่สมควรได้รับการเข้าถึงได้โดยตรงควรไม่เคยเป็น typedef
ปรากฎว่ามีข้อดีและข้อเสีย แหล่งข้อมูลที่มีประโยชน์คือหนังสือ "การเขียนโปรแกรมผู้เชี่ยวชาญ C" ( บทที่ 3 ) สั้น ๆ ใน C คุณมี namespaces หลายแท็กประเภทชื่อสมาชิกและตัวบ่งชี้ 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
ไม่ได้
ในหนังสือที่กล่าวถึงข้างต้นกล่าวถึงว่าการพิมพ์การจัดเรียงไม่ได้มีประโยชน์มากเพราะช่วยให้โปรแกรมเมอร์ไม่สามารถเขียนคำว่า 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
) โดย struct ภายใน ( MyPipe
) ผ่านการคัดเลือกนักแสดง สำหรับฉันมันมีความสับสนน้อยกว่าที่จะแสดงทั้งแบบ(struct MyWriter_ *) s;
ทุกครั้งที่คุณต้องการใช้งานฟังก์ชั่นดังกล่าว ในกรณีเหล่านี้อ้างอิงสั้น ๆ เป็นเรื่องใหญ่โดยเฉพาะอย่างยิ่งถ้าคุณใช้เทคนิคในรหัสของคุณ
ในที่สุดด้านสุดท้ายที่มีtypedef
ประเภท ed คือการไม่สามารถขยายพวกเขาในทางตรงกันข้ามกับแมโคร ตัวอย่างเช่นคุณมี:
#define X char[10] or
typedef char Y[10]
จากนั้นคุณสามารถประกาศ
unsigned X x; but not
unsigned Y y;
เราไม่สนใจสิ่งนี้สำหรับ structs เพราะไม่ได้ใช้กับตัวระบุหน่วยเก็บข้อมูล ( volatile
และconst
)
MyPipe *s; MyWriter *self = (MyWriter *) s;
และคุณเพิ่งเสียนามแฝงที่เข้มงวด
typedef struct Tag{ ...members... }Type;
"กำหนดสองสิ่ง" ไม่สมเหตุสมผล หาก typedef กำหนดแท็กแล้ว 'ประเภท' ที่นี่ควรเป็นแท็ก ความจริงก็คือความหมายกำหนด 2 แท็กและประเภท 1 (หรือ 2 ประเภทและ 1 แท็กไม่แน่ใจว่า.) struct Tag
, และTag
เป็นประเภทแน่นอน เป็นแท็ก แต่ความสับสนก็คือไม่ว่าจะเป็นแท็กหรือประเภทType
struct Tag
Tag
Type
ฉันไม่คิดว่าการประกาศล่วงหน้าจะเป็นไปได้ด้วย typedef การใช้ struct, enum และ union อนุญาตให้ส่งต่อการประกาศเมื่อการพึ่งพา (รู้เกี่ยวกับ) เป็นแบบสองทิศทาง
สไตล์: การใช้ typedef ใน C ++ ค่อนข้างสมเหตุสมผล เกือบจะจำเป็นเมื่อจัดการกับแม่แบบที่ต้องการพารามิเตอร์หลายตัวและ / หรือตัวแปร typedef ช่วยให้การตั้งชื่อตรง
ไม่เช่นนั้นในภาษา C การใช้ typedef ส่วนใหญ่มักจะไม่มีจุดประสงค์ แต่เพื่อทำให้สับสนการใช้งานโครงสร้างข้อมูล เนื่องจากมีเพียง {struct (6), enum (4), union (5)} จำนวน keystrokes ที่ใช้ในการประกาศชนิดข้อมูลที่แทบจะไม่ใช้นามแฝงของ struct เป็นข้อมูลที่พิมพ์สหภาพหรือ struct หรือไม่? การใช้การประกาศที่ไม่พิมพ์ผิดตรงไปตรงมาช่วยให้คุณทราบได้ทันทีว่ามันเป็นประเภทใด
โปรดสังเกตว่าการเขียนลีนุกซ์ด้วยการหลีกเลี่ยงอย่างเข้มงวดเกี่ยวกับเรื่องไร้สาระนามแฝง typedef นี้นำมาอย่างไร ผลลัพธ์ที่ได้คือสไตล์ที่เรียบง่ายและสะอาดตา
struct
ทุกที่ ... ประเภทของ Typedef ที่สร้างขึ้นใหม่ คุณใช้อะไร ประเภท เราไม่สนใจว่ามันคือโครงสร้างสหภาพหรือ enum นั่นคือสาเหตุที่เราพิมพ์มัน
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 เพื่อแสดงถึงชื่อประเภทไลบรารีมาตรฐาน
ชื่อที่คุณ (เป็นทางเลือก) ให้โครงสร้างนั้นเรียกว่าชื่อแท็กและตามที่ได้รับการจดบันทึกแล้วไม่ใช่ประเภทในตัวเอง ในการไปที่ชนิดต้องใช้คำนำหน้า struct
GTK + นอกเหนือจากกันฉันไม่แน่ใจว่ามีการใช้ tagname เหมือนปกติเหมือนกับ typedef ของประเภท struct ดังนั้นใน C ++ ที่เป็นที่รู้จักและคุณสามารถละเว้นคำหลัก struct และใช้ 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> งาน โครงสร้างกำหนดประเภท โครงสร้างช่วยให้จัดกลุ่มคอลเลกชัน vars ได้สะดวกเพื่อความสะดวกในการจัดการ (K&R, pg127, C prog lang.) เป็นหน่วยเดียว
C> typedef'ing struct อธิบายไว้ใน A ข้างต้น
D> สำหรับฉัน structs เป็นประเภทที่กำหนดเองหรือภาชนะบรรจุหรือคอลเลกชันหรือเนมสเปซหรือประเภทที่ซับซ้อนในขณะที่ typdef เป็นเพียงวิธีในการสร้างชื่อเล่นมากขึ้น
ปรากฎใน C99 typedef เป็นสิ่งจำเป็น มันล้าสมัย แต่เครื่องมือจำนวนมาก (ala HackRank) ใช้ c99 เป็นการใช้งาน C บริสุทธิ์ และจำเป็นต้องมี typedef
ฉันไม่ได้บอกว่าพวกเขาควรเปลี่ยน (อาจมีสองตัวเลือก C) หากความต้องการเปลี่ยนแปลงไปพวกเราที่กำลังศึกษาเพื่อสัมภาษณ์ในเว็บไซต์จะเป็น SOL
typedef
" คุณหมายถึงอะไร
C
C++
ในC
typedefs คือ 'ต้องการ' (และมักจะเป็น) 'ต้องใช้' ในขณะที่คุณจะไม่สามารถที่จะประกาศตัวแปรPoint varName;
และมีประเภทจะตรงกันกับที่ไม่มีstruct Point;
typedef struct Point Point;
ในภาษาการเขียนโปรแกรม 'C' คำหลัก 'typedef' จะใช้เพื่อประกาศชื่อใหม่สำหรับวัตถุบางอย่าง (struct, array, function..enum type) ตัวอย่างเช่นฉันจะใช้ 'struct-s' ใน 'C' เรามักจะประกาศ 'struct' นอกฟังก์ชั่น 'main' ตัวอย่างเช่น:
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 ฉันจะต้องใช้คำสำคัญ 'struct' บางอย่าง '' ชื่อ '' 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
นั่นก็เป็นเหตุผลว่าทำไมมันถึงไร้สาระที่จะมีโครงสร้างแบบพึ่งพาตนเอง, ตัวประมวลผล pre C ในรอบการวนซ้ำที่ไม่สามารถยุติได้
typedef เป็นตัวระบุชนิดซึ่งหมายถึงเฉพาะคอมไพเลอร์ C ที่ประมวลผลและสามารถทำเช่นเดียวกับที่เขาต้องการสำหรับการปรับใช้โค้ดแอสเซมเบลอร์ให้เหมาะสม นอกจากนี้ยังไม่ใช้จ่ายสมาชิกประเภท par อย่างโง่เขลาเหมือนpréprocessorทำกับ structs แต่ใช้อัลกอริทึมการก่อสร้างอ้างอิงที่ซับซ้อนมากขึ้นดังนั้นการก่อสร้างเช่น:
typedef struct a A; //anticipated declaration for member declaration
typedef struct a //Implemented declaration
{
A* b; // member declaration
}A;
ได้รับอนุญาตและทำงานได้อย่างสมบูรณ์ การใช้งานนี้ให้การเข้าถึงการแปลงประเภทคอมไพเลอร์และลบเอฟเฟกต์การบั๊กบางส่วนเมื่อเธรดการดำเนินการออกจากฟิลด์แอปพลิเคชันของฟังก์ชันการเริ่มต้น
นี่หมายความว่าใน C typedefs นั้นใกล้เคียงกับคลาส C ++ มากกว่า structon ที่อ้างว้าง
structs
และtypedef
s นั้นไม่ดีพอ แต่การเขียนที่เหลือของคุณนั้นสับสนจนฉันคิดว่ามันยากที่จะรับข้อความใด ๆ จากมัน สิ่งหนึ่งที่ผมสามารถพูดได้ แต่เป็นที่ความคิดของคุณว่าไม่ใช่typedef
d struct
ไม่สามารถคาดการณ์ล่วงหน้าหรือประกาศใช้เป็นสีขาวขุ่น (ตัวชี้) สมาชิกเป็นเท็จโดยสิ้นเชิง ในตัวอย่างที่ 1 ของคุณstruct b
สามารถมี a struct a *
, ไม่typedef
จำเป็น การยืนยันที่struct
เป็นเพียงการขยายตัวในระดับมหึมาและนั่นtypedef
ทำให้พวกเขามีพลังอำนาจใหม่ที่ปฏิวัติวงการได้อย่างไม่ถูกต้องอย่างเจ็บปวด