ถ้าโครงสร้างนี้จะใช้กับ func.c ไฟล์อื่นจะทำอย่างไร?
เมื่อใช้ชนิดในไฟล์ (เช่นไฟล์ func.c) จะต้องมองเห็นได้ วิธีที่แย่ที่สุดคือคัดลอกวางในไฟล์ต้นฉบับแต่ละไฟล์ที่จำเป็น
วิธีที่ถูกต้องคือการวางไว้ในไฟล์ส่วนหัวและรวมไฟล์ส่วนหัวนี้ทุกครั้งที่ต้องการ
เราจะเปิดไฟล์ส่วนหัวใหม่และประกาศโครงสร้างที่นั่นและรวมส่วนหัวนั้นไว้ใน func.c หรือไม่?
นี่เป็นวิธีแก้ปัญหาที่ฉันชอบมากกว่าเพราะมันทำให้โค้ดเป็นโมดูลาร์สูง ฉันจะเขียนโครงสร้างของคุณเป็น:
#ifndef SOME_HEADER_GUARD_WITH_UNIQUE_NAME
#define SOME_HEADER_GUARD_WITH_UNIQUE_NAME
struct a
{
int i;
struct b
{
int j;
}
};
#endif
ฉันจะใส่ฟังก์ชันที่ใช้โครงสร้างนี้ในส่วนหัวเดียวกัน (ฟังก์ชันที่เป็นส่วน "อินเตอร์เฟส" ของมัน)
และโดยปกติฉันสามารถตั้งชื่อไฟล์ตามชื่อโครงสร้างและใช้ชื่อนั้นอีกครั้งเพื่อเลือกตัวป้องกันส่วนหัวกำหนด
หากคุณต้องการประกาศฟังก์ชันโดยใช้ตัวชี้ไปที่โครงสร้างคุณไม่จำเป็นต้องใช้นิยามโครงสร้างแบบเต็ม การประกาศล่วงหน้าง่ายๆเช่น:
struct a ;
จะเพียงพอและลดการมีเพศสัมพันธ์
หรือเราสามารถกำหนดโครงสร้างทั้งหมดในไฟล์ส่วนหัวและรวมไว้ใน source.c และ func.c ได้หรือไม่
นี่เป็นอีกวิธีหนึ่งที่ง่ายกว่า แต่แบบแยกส่วนน้อย: โค้ดบางตัวที่ต้องการเพียงโครงสร้างของคุณในการทำงานก็ยังต้องรวมทุกประเภท
ใน C ++ สิ่งนี้อาจนำไปสู่ความซับซ้อนที่น่าสนใจ แต่สิ่งนี้ไม่อยู่ในหัวข้อ (ไม่มีแท็ก C ++) ดังนั้นฉันจะไม่อธิบายอย่างละเอียด
แล้วจะประกาศโครงสร้างนั้นเป็นภายนอกในไฟล์ทั้งสองได้อย่างไร ?
บางทีฉันไม่เห็นประเด็น แต่ Greg Hewgill มีคำตอบที่ดีมากในโพสต์ของเขาจะประกาศโครงสร้างในส่วนหัวที่จะใช้โดยไฟล์หลายไฟล์ใน c ได้อย่างไร? .
แล้วเราจะพิมพ์มันยังไง?
- หากคุณกำลังใช้ C ++ อย่า
- หากคุณใช้ C คุณควร
เหตุผลที่การจัดการโครงสร้าง C อาจเป็นความเจ็บปวด: คุณต้องประกาศคำหลักโครงสร้างทุกที่ที่ใช้:
struct MyStruct ; /* Forward declaration */
struct MyStruct
{
/* etc. */
} ;
void doSomething(struct MyStruct * p) /* parameter */
{
struct MyStruct a ; /* variable */
/* etc */
}
ในขณะที่ typedef จะช่วยให้คุณสามารถเขียนได้โดยไม่ต้องใช้คีย์เวิร์ด struct
struct MyStructTag ; /* Forward declaration */
typedef struct MyStructTag
{
/* etc. */
} MyStruct ;
void doSomething(MyStruct * p) /* parameter */
{
MyStruct a ; /* variable */
/* etc */
}
เป็นสิ่งสำคัญที่คุณจะต้องตั้งชื่อให้กับโครงสร้าง การเขียน:
typedef struct
{
/* etc. */
} MyStruct ;
จะสร้างโครงสร้างที่ไม่ระบุตัวตนด้วยชื่อ typedef-ed และคุณจะไม่สามารถประกาศไปข้างหน้าได้ ดังนั้นให้ใช้รูปแบบต่อไปนี้:
typedef struct MyStructTag
{
/* etc. */
} MyStruct ;
ดังนั้นคุณจะสามารถใช้ MyStruct ทุกที่ที่คุณต้องการหลีกเลี่ยงการเพิ่มคีย์เวิร์ด struct และยังคงใช้ MyStructTag เมื่อ typedef ไม่ทำงาน (เช่นการประกาศไปข้างหน้า)
แก้ไข:
แก้ไขสมมติฐานผิดเกี่ยวกับ C99 ประกาศ struct เป็นข้อสังเกตชอบธรรมโดยโจนาธาน Leffler
แก้ไข 2018-06-01:
Craig Barnesเตือนเราในความคิดเห็นของเขาว่าคุณไม่จำเป็นต้องเก็บชื่อแยกต่างหากสำหรับชื่อ struct "tag" และชื่อ "typedef" เหมือนที่ฉันทำข้างต้นเพื่อความชัดเจน
อันที่จริงรหัสข้างต้นสามารถเขียนได้เป็น:
typedef struct MyStruct
{
/* etc. */
} MyStruct ;
IIRC นี่คือสิ่งที่ C ++ ทำกับการประกาศโครงสร้างที่ง่ายกว่าเบื้องหลังเพื่อให้เข้ากันได้กับ C:
// C++ explicit declaration by the user
struct MyStruct
{
/* etc. */
} ;
// C++ standard then implicitly adds the following line
typedef MyStruct MyStruct;
กลับไปที่ C ฉันเคยเห็นการใช้งานทั้งสองแบบ (ชื่อที่แยกจากกันและชื่อเดียวกัน) และไม่มีข้อเสียใด ๆ ที่ฉันรู้ดังนั้นการใช้ชื่อเดียวกันจะทำให้การอ่านง่ายขึ้นหากคุณไม่ใช้"เนมสเปซ" แยกต่างหากสำหรับโครงสร้างและสัญลักษณ์อื่น ๆ .
struct b
แต่โครงสร้างของคุณจะa
ประกาศประเภทที่ไม่ได้ใช้ (คุณควรกำหนดชื่อสมาชิกk
ไว้หลังวงเล็บปีกกาปิดด้านในและ ก่อนอัฒภาค