c - 多重定义并确保正确编写函数
问题描述
这是我的 .h 文件
#ifndef _test_h_
#define _test_h_
void new_cmd(void);
void open_cmd(void);
void close_cmd(void);
void close_all_cmd(void);
void save_cmd(void);
void save_as_cmd(void);
void save_all_cmd(void);
void print_cmd(void);
void exit_cmd(void);
void call(char *cmd_name);
struct {
char *cmd_name;
void (*cmd_pointer)(void);
} file_cmd[] =
{
{"new", new_cmd},
{"open", open_cmd},
{"close", close_cmd},
{"save", save_cmd},
{"save as", save_as_cmd},
{"save all", save_all_cmd},
{"print", print_cmd},
{"exit", exit_cmd}};
#endif
这是我的函数文件
void call(char *cmd_name){
int i;
scanf("Enter command: %c\n",cmd_name);
for(i = 0; i < sizeof(file_cmd); i++){
if(strcmp(cmd_name, file_cmd[i].cmd_name) == 0){
file_cmd[i].cmd_pointer();
}
}
我刚刚删除了所有 file_cmd 函数,因为它似乎对其他人来说
这是我的主要文件
#include <stdio.h>
#include <string.h>
#include "test.h"
int main(void){
char cmd;
call(cmd);
return 0;
}
我想知道的更多是我的函数 void 调用是否正确编写。
当我尝试编译时,它说
- 预期为 'char*' 但参数的类型为 'char'
- 'file_cmd' 的多重定义
- 首先在这里定义。
我很困惑如何解决它。
请帮忙
谢谢你。
解决方案
您有两个非常不同的错误,您确实应该在两个不同的问题中提出这些错误,但是无论如何我都会很好地回答这两个问题。
在
main
函数中,您有一个名为cmd
. 它是类型char
。您将它传递给call
函数,该函数需要一个类型的参数char *
(即以空字符结尾的字符串)。要解决此问题,您首先需要确保它
cmd
是正确的类型(即char *
,而不是 plainchar
)。其次,您需要确保该指针实际上指向一个有效的以空值结尾的字节字符串。换句话说,是这样的:
char *cmd = "open"; call(cmd);
C 真的只关心翻译单元。翻译单元是包含所有头文件的单个源文件。
这里的问题是变量只能在单个翻译单元中定义。由于您在包含在多个源文件中的头文件中定义变量
file_cmd
,因此它将在从这两个源文件创建的两个翻译单元中定义。这里的解决方案是只在头文件中声明变量,并在单个源文件中定义。
例如,在头文件中做这样的事情
struct command_struct { char *cmd_name; void (*cmd_pointer)(void); }; extern struct command_struct file_cmd[];
然后在一个源文件中(比如你的“函数文件”)
struct command_struct file_cmd[] = { // Your initialization... };
您的代码还有其他问题,其中一些会导致未定义的行为。
例如,运算符以字节为单位sizeof
返回大小,而不是数组中的元素数。要获取数组中元素的数量,您需要将整个数组的字节大小除以单个元素的字节大小。例如.sizeof file_cmd / file_cmd[0]
请注意,除法仅适用于真正的数组,而不是指针,并且数组很容易衰减为指针(指向它们的第一个元素)。
推荐阅读
- python - 将对象列表写入 JSON 文件
- python - 遍历日期范围并对值求和
- spring - 为什么 Spring Integration QueueChannel 与 kafka 中的延迟传递消息顺序运行
- c - 从不兼容的指针类型传递 fwrite 的参数 4
- azure-cosmosdb - 如何知道分区键在 Cosmos DB 中是否正常工作
- ios - 集合视图:UIViewRepresentable + NavigationView
- oracle - 使用“而不是删除”创建触发器
- sql - 在 myBatis 查询中设置 java.time.LocalDate 作为参数
- node.js - 在多个微服务上使用猫鼬模式
- css - Sass 未定义变量,即使我已经先导入了它们