结构体的声明(extern)与调用的方式

本文介绍如何正确地在多个C源文件中使用同一个结构体定义,避免重复定义错误。通过将结构体类型定义与变量声明分离,确保代码的可读性和可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

结构体的声明(extern)与调用的方式  ( 转载 )


要求如下,在.h文件中这样定义:

 

typedef struct typFNT_GB16                 // 汉字字模数据结构
{
       signed char Index[2];               // 汉字内码索引
       char Msk[32];                       // 点阵码数据
};

struct typFNT_GB16 code GB_16[] =          // 数据表
{
"我", 0x20,0x24,0x24,0x24,0xFE,0x23,0x22,0x20,
      0xFF,0x20,0x22,0xAC,0x20,0x30,0x20,0x00,
      0x00,0x08,0x48,0x84,0x7F,0x02,0x21,0x10,
      0x09,0x06,0x1A,0x61,0x80,0xE0,0x00,0x00,
"们", 0x40,0x20,0xF8,0x07,0x00,0xF8,0x02,0x04,
      0x08,0x04,0x04,0x04,0x04,0xFE,0x04,0x00,
      0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,
      0x00,0x00,0x00,0x40,0x80,0x7F,0x00,0x00
};
 
同时需要在多个.c文件中使用该struct, 但是多次include 该.h文件提示重复定义,应该修改如下:


新建一个xx.h和xx.c文件

在xx.h文件中定义该结构体,同时对结构体变量作extern:

typedef struct typFNT_GB16 // 汉字字模数据结构
{
signed char Index[2]; // 汉字内码索引
char Msk[32]; // 点阵码数据
};
extern struct typFNT_GB16 code GB_16[];
 
在xx.c文件中include该.h文件,同时作结构体变量的初始化:
#include "xx.h"


struct typFNT_GB16 code GB_16[] = // 数据表

{
"我", 0x20,0x24,0x24,0x24,0xFE,0x23,0x22,0x20,
0xFF,0x20,0x22,0xAC,0x20,0x30,0x20,0x00,
0x00,0x08,0x48,0x84,0x7F,0x02,0x21,0x10,
0x09,0x06,0x1A,0x61,0x80,0xE0,0x00,0x00,
"们", 0x40,0x20,0xF8,0x07,0x00,0xF8,0x02,0x04,
0x08,0x04,0x04,0x04,0x04,0xFE,0x04,0x00,
0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,
0x00,0x00,0x00,0x40,0x80,0x7F,0x00,0x00

};

在其它.c文件中需要使用该结构体时,直接include .h文件即可这样编译通过。实际上结构体是一种数据类型,.h文件定义了一种类型的结构体,并声明为extern形式允许外部调用它,而初始化code GB_16[] 这个结构体应当在.c文件中进行。


类型的定义和类型变量的定义不同,类型定义只是描述一个类型,是给编译器看的,不会产生可执行代码。变量定义是指在执行文件中真实的存在这么一块内容。因此,类型定义可以重复出现也没关系,类型变量是不能在多个.c中出现,否则就是重复定义。因为每个.c里都要写清楚类型定义很麻烦,所以一般都把类型定义写在.h里,而在.c里采用简单的写




<think>好的,我现在需要回答用户关于在C语言中使用extern关键字结构体相关的内容,包括使用方法和示例代码。首先,我得回忆一下extern关键字的基本作用。extern在C语言中主要用于声明变量或函数,表明其定义在别的文件中,或者在当前文件的后面部分。这对于多文件项目中的全局变量和函数共享非常重要。 接下来,结构体在C语言中是一种用户自定义的数据类型,可以将不同类型的数据组合在一起。当结构体需要跨文件使用时,extern的应用场景可能包括在头文件中声明结构体类型,并在其他文件中引用该头文件,或者在多个文件中共享同一个结构体变量。用户的问题可能涉及如何在不同的源文件中使用extern来共享结构体变量或结构体类型。需要明确的是,结构体类型的声明通常放在头文件中,而不是使用extern,因为extern主要用于变量和函数的声明,而不是类型定义。不过,如果在某个源文件中定义了一个结构体变量,并希望在另一个文件中使用它,就需要用extern声明该变量。例如,假设在file1.c中定义了一个结构体变量structPerson p1;,在file2.c中要使用这个变量,就需要在file2.c中使用extern structPerson p1;来声明,这样编译器就知道该变量在别处定义,链接时会找到它。另外,需要注意的是,结构体类型的定义本身需要在所有使用它的文件中可见,通常是通过包含同一个头文件来实现的。如果结构体类型在头文件中定义,那么各个包含该头文件的源文件都可以使用该结构体类型,不需要使用extern。可能用户会混淆结构体类型的声明结构体变量的extern使用。需要明确区分两者的不同。结构体类型声明属于类型定义,而extern用于变量或函数的声明。因此,当需要在多个文件中共享同一个结构体变量时,才使用extern,而结构体类型的定义应放在头文件中。此外,示例代码可能会帮助用户理解。例如,在头文件中定义结构体类型,在一个源文件中定义结构体变量,并在另一个源文件中使用extern来引用该变量。这样,用户可以看到如何正确地在多文件项目中共享结构体变量。 同时,需要注意避免重复定义结构体类型,这会导致编译错误。因此,头文件中应使用头文件保护(如#ifndef...#define...#endif)来防止多次包含。总结一下,回答需要涵盖以下几点:1.extern关键字的作用:声明变量或函数,定义在别处。2.结构体类型通常在头文件中定义,供多个源文件包含。 3.结构体变量在定义它的文件中定义,其他文件使用extern声明该变量。4.示例代码展示如何在多文件中使用extern共享结构体变量。5.注意事项,如头文件保护和避免重复定义。 需要确保示例代码正确,语法无误,并且注释清晰,帮助用户理解每个步骤。同时,可能还需要提到链接时的处理,确保变量在链接时被正确找到,避免未定义的引用错误。最后,生成相关问题,帮助用户进一步学习,比如extern全局变量的关系,结构体定义的最佳实践,或者多文件编程中的常见问题。</think>### C语言中extern关键字结构体的使用方法 在C语言中,`extern`关键字用于声明变量或函数,表示其实际定义在其他文件中。结合结构体使用时,主要用于跨文件共享结构体变量或函数。以下是具体说明和示例: --- #### 1. **结构体类型定义extern的关系** - **结构体类型定义**:通常放在头文件(`.h`)中,确保所有使用该类型的文件都能包含同一份定义。 ```c // person.h #ifndef PERSON_H #define PERSON_H struct Person { char name[20]; int age; }; #endif ``` - **extern的作用**:不用于声明结构体类型,而是用于声明**结构体变量**或**函数**,表明其定义在其他文件中。 --- #### 2. **跨文件共享结构体变量** - **步骤**: 1. 在源文件(如`file1.c`)中定义结构体变量。 2. 在头文件(如`person.h`)中用`extern`声明该变量。 3. 其他文件(如`file2.c`)包含头文件后可直接使用该变量。 - **示例代码**: ```c // person.h extern struct Person global_person; // 声明变量,实际定义在file1.c中 // file1.c #include "person.h" struct Person global_person = {"Alice", 25}; // 定义变量 // file2.c #include "person.h" void print_person() { printf("Name: %s, Age: %d\n", global_person.name, global_person.age); // 直接使用extern变量 } ``` --- #### 3. **跨文件调用结构体相关函数** 若函数返回结构体类型或操作结构体变量,可在头文件中用`extern`声明函数: ```c // person.h extern struct Person create_person(const char* name, int age); // 声明函数 // file1.c struct Person create_person(const char* name, int age) { struct Person p; strcpy(p.name, name); p.age = age; return p; } // file2.c #include "person.h" void example() { struct Person p = create_person("Bob", 30); // 调用外部函数 } ``` --- #### 4. **注意事项** 1. **避免重复定义**:结构体类型需通过头文件保护(`#ifndef`)防止多次包含。 2. **变量初始化**:`extern`声明的变量不能直接初始化,需在定义时赋值。 3. **链接一致性**:确保所有文件在编译时链接到变量或函数的定义。 --- ### 示例代码汇总 ```c // person.h #ifndef PERSON_H #define PERSON_H struct Person { char name[20]; int age; }; extern struct Person global_person; // 声明变量 extern struct Person create_person(const char* name, int age); // 声明函数 #endif // file1.c #include "person.h" struct Person global_person = {"Alice", 25}; // 定义变量 struct Person create_person(const char* name, int age) { struct Person p; strcpy(p.name, name); p.age = age; return p; } // file2.c #include "person.h" #include <stdio.h> void main() { printf("Global Person: %s, %d\n", global_person.name, global_person.age); // 使用extern变量 struct Person p = create_person("Bob", 30); // 调用extern函数 } ``` --- ###
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值