修正对extern的一些误解

本文通过一个具体的示例,解释了在C语言中如何正确理解和使用extern关键字,并展示了如何通过extern来引用其他文件中定义的变量。实验证明,通过extern声明的变量不仅可以被调用,还可以被修改。

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

之前使用extern作为编译器的链接关键词时,潜意识以为,在extern声明的代码中只能调用而不能改变,其实这只是方便编译的,最终还是生成一个object文件,是可以修改的,
在实验楼linux64位实验如下

shiyanlou:Code/ $ cat returna.c                                      [10:28:59]
int a=0;
int backa()
{
    return a;
}
shiyanlou:Code/ $ cat main.c                                         [10:29:04]
#include<stdio.h>
extern int a;
int main()
{
    int b;
    a=12;
    b=backa();
    printf("b=%d\n",b);
    return 0;
}
shiyanlou:Code/ $ gcc main.c returna.c -o main                       [10:31:48]
shiyanlou:Code/ $ ./main                                             [10:32:29]
b=12
#include "RTX51TNY.H" #include "Fingerprint.h" // 任务ID定义 #define MAIN_TASK_ID 0 #define FP_TASK_ID 1 // 指纹操作结果回调函数 void fp_callback(u8 status, u16 id) { if(status) { printf("Operation success! ID: %d\n", id); P13 = 0; } else { printf("Operation failed! ID: %d\n", id); P13 = 1; } } void setup() { EAXSFR(); EA = 1; ZW101_init(); ZW101_set_callback(fp_callback); } void main_task() _task_ MAIN_TASK_ID { setup(); printf("Fingerprint System Start\n"); os_create_task(FP_TASK_ID); os_delete_task(MAIN_TASK_ID); } void fp_task() _task_ FP_TASK_ID { // 这里需要添加实际的按钮检测代码 // 使用临时变量代替按钮状态 u8 check_button = 0; u8 enroll_button = 0; u8 sleep_button = 0; while(1) { // 示例:检测按钮按下触发指纹检测 if(check_button) { if(!ZW101_is_busy()) { ZW101_start_check(); } } // 示例:录入按钮按下触发指纹录入 else if(enroll_button) { if(!ZW101_is_busy()) { ZW101_start_enroll(1); } } // 示例:休眠按钮按下进入低功耗 else if(sleep_button) { ZW101_sleep(); } // 处理接收数据 if(ZW101_is_busy()) { ZW101_receive_data(); } os_wait2(K_IVL, 10); } } 这是指纹模块的main.c文件 #include "Fingerprint.h" // 指令定义 static const u8 cmd_sleep[] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x03,0x33,0x00,0x37}; static const u8 cmd_wakeup[] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x03,0x34,0x00,0x38}; static const u8 cmd_check[] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x08,0x32,0x02,0xFF,0xFF,0x00,0x01,0x02,0x3C}; static const u8 cmd_enroll_start[] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x04,0x31,0x00,0x36}; static const u8 cmd_enroll1[] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x04,0x31,0x01,0x37}; static const u8 cmd_enroll2[] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x04,0x31,0x02,0x38}; static const u8 cmd_enroll3[] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x04,0x31,0x03,0x39}; // 模块状态变量 static u8 connected = 0; static u8 current_mode = FP_MODE_IDLE; static u16 enroll_id = 0; static u8 enroll_step = 0; static fp_callback_t user_callback = NULL; void ZW101_GPIO_config() { // 配置GPIO引脚 P4_MODE_IO_PU(GPIO_Pin_3 | GPIO_Pin_4); P13 = 1; // 低功耗模式,拉高启动 } void ZW101_UART_config() { // 配置UART串口 COMx_InitDefine init; init.UART_Mode = UART_8bit_BRTx; init.UART_BaudRate = 115200UL; init.UART_RxEnable = ENABLE; init.BaudRateDouble = DISABLE; init.UART_BRT_Use = BRT_Timer1; UART_Configuration(UART1, &init); UART1_SW(UART1_SW_P30_P31); NVIC_UART1_Init(ENABLE, Priority_0); } void ZW101_send_cmd(const u8 *cmd, u8 len) { // 发送指令到指纹模块 u8 i; for(i = 0; i < len; i++) { TX2_write2buff(cmd[i]); } } void ZW101_init() { // 初始化指纹模块 ZW101_GPIO_config(); ZW101_UART_config(); current_mode = FP_MODE_IDLE; } void ZW101_set_mode(u8 mode) { // 设置当前操作模式 current_mode = mode; } u8 ZW101_is_busy() { // 检查模块是否忙 return (current_mode != FP_MODE_IDLE && current_mode != FP_MODE_SLEEP); } void ZW101_sleep() { // 进入低功耗模式 ZW101_send_cmd(cmd_sleep, sizeof(cmd_sleep)); current_mode = FP_MODE_SLEEP; } void ZW101_wakeup() { // 从低功耗模式唤醒 ZW101_send_cmd(cmd_wakeup, sizeof(cmd_wakeup)); current_mode = FP_MODE_IDLE; } void ZW101_start_check() { // 开始指纹检测 ZW101_send_cmd(cmd_check, sizeof(cmd_check)); current_mode = FP_MODE_CHECK; } void ZW101_start_enroll(u16 id) { // 开始指纹录入 enroll_id = id; enroll_step = 0; ZW101_send_cmd(cmd_enroll_start, sizeof(cmd_enroll_start)); current_mode = FP_MODE_ENROLL; } void ZW101_set_callback(fp_callback_t callback) { // 设置结果回调函数 user_callback = callback; } void ZW101_process_response(u8 *data, u8 len) { // 处理模块响应 u8 cmd; u8 param; u16 fid; // 检查响应长度是否足够 if(len < 12) return; // 验证包头 if(data[0] != FP_SYNO_FIRST_HEAD || data[1] != FP_SYNO_SECOND_HEAD) return; cmd = data[9]; param = data[10]; // 根据当前模式处理响应 switch(current_mode) { case FP_MODE_CHECK: if(param == 0x05) { if(cmd == 0x00) { fid = (data[11] << 8) | data[12]; if(user_callback) user_callback(1, fid); } else { if(user_callback) user_callback(0, 0); } } current_mode = FP_MODE_IDLE; break; case FP_MODE_ENROLL: if(param == 0x31) { if(cmd == 0x00) { enroll_step++; if(enroll_step == 1) { ZW101_send_cmd(cmd_enroll1, sizeof(cmd_enroll1)); } else if(enroll_step == 2) { ZW101_send_cmd(cmd_enroll2, sizeof(cmd_enroll2)); } else if(enroll_step == 3) { ZW101_send_cmd(cmd_enroll3, sizeof(cmd_enroll3)); } else { if(user_callback) user_callback(1, enroll_id); current_mode = FP_MODE_IDLE; } } else { if(user_callback) user_callback(0, enroll_id); current_mode = FP_MODE_IDLE; } } break; default: break; } } void ZW101_receive_data() { // 接收并处理数据 u8 i; // 检查是否有超时数据 if(COM2.RX_TimeOut > 0 && --COM2.RX_TimeOut == 1) { if(COM2.RX_Cnt > 0) { // 初始连接确认 if(!connected) { for(i = 0; i < COM2.RX_Cnt; i++) { if(RX2_Buffer[i] == 0x55) { connected = 1; break; } } } // 处理有效数据包 if(COM2.RX_Cnt >= 12) { ZW101_process_response(RX2_Buffer, COM2.RX_Cnt); } } COM2.RX_Cnt = 0; } } 这是指纹模块的Fingerprint.c文件 #ifndef _ZW101_H_ #define _ZW101_H_ #include "STC8G_H_GPIO.h" #include "STC8G_H_UART.h" #include "STC8G_H_Switch.h" #include "STC8G_H_NVIC.h" #include "STC8G_H_Delay.h" // 操作模式定义 #define FP_MODE_IDLE 0 // 空闲模式 #define FP_MODE_CHECK 1 // 指纹验证模式 #define FP_MODE_ENROLL 2 // 指纹录入模式 #define FP_MODE_SLEEP 3 // 休眠模式 // 协议定义 #define FP_SYNO_FIRST_HEAD 0xEF // 包头第一字节 #define FP_SYNO_SECOND_HEAD 0x01 // 包头第二字节 #define FP_SYNO_CMD_PKG 0x01 // 命令包标识 #define FP_SYNO_DATA_PKG 0x02 // 数据包 #define FP_SYNO_EOF_PKG 0x08 // 结束包 #define GET_ARRAY_LEN(arr) (sizeof(arr)/sizeof((arr)[0])) // 计算数组长度 // 定义函数指针类型 typedef void (*fp_callback_t)(u8 status, u16 id); // 函数声明 void ZW101_init(void); void ZW101_set_mode(u8 mode); u8 ZW101_is_busy(void); void ZW101_receive_data(void); void ZW101_sleep(void); void ZW101_wakeup(void); void ZW101_start_enroll(u16 id); void ZW101_start_check(void); void ZW101_set_callback(fp_callback_t callback); // 回调函数声明 extern void ZW101_check_success(void); extern void ZW101_check_error(void); extern void ZW101_check_timeout(void); #endif 这是指纹模块的Fingerprint.h文件,为什么在main.c中编译会出现以下错误 Fingerprint.c(95): error C141: syntax error near ',', expected '<id>' Fingerprint.c(105): error C141: syntax error near 'data', expected 'sizeof' Fingerprint.c(108): error C141: syntax error near 'data', expected 'sizeof' Fingerprint.c(108): error C141: syntax error near ']', expected ';' Fingerprint.c(109): error C141: syntax error near 'data', expected 'sizeof' Fingerprint.c(109): error C141: syntax error near ']', expected ';' Fingerprint.c(116): error C141: syntax error near '[', expected 'bit' Fingerprint.c(116): error C141: syntax error near ']', expected ';' Fingerprint.c(116): error C141: syntax error near ')', expected ';' Fingerprint.c(116): error C141: syntax error near ']', expected ';' Fingerprint.c(170): error C208: '_ZW101_process_response': too many actual parameters
最新发布
07-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值