在 h 文件中找不到函数定义

function definition not found in h file

我不太明白Visual Studio2019要我干什么(C语言)。一方面,它不会向我抛出错误或警告,但另一方面,它会在我的 API 文件中用绿色波浪线标记我的 createCustomer 声明。我想封装Customer,在Customer结构上使用ADT。

这些是我的源文件和头文件:

customer.h

#include <stdlib.h>

typedef struct Customer
{
    unsigned int customerId;
    const char* name;
    int numOrders;
}Customer, * CustomerPtr;

customer.c

#include "customer.h"

#define MAX_NO_OF_CUSTOMERS 10
static Customer objectPool[MAX_NO_OF_CUSTOMERS];
static unsigned int customersCount = 0;

CustomerPtr createCustomer(const char* name, size_t numOrders)
{
    CustomerPtr newCustomer_p = NULL;
    if(customersCount < MAX_NO_OF_CUSTOMERS)
    {
        newCustomer_p = objectPool + (customersCount++);
        newCustomer_p->name = name;
        newCustomer_p->numOrders = numOrders;
    }
}

customer_api.h

#include "customer.h"

CustomerPtr createCustomer(const char* name, int numOrders);

main.c

#include <stdio.h>
#include "main.h"
#include "customer_api.h"

int main()
{
    CustomerPtr customer_p = createCustomer("Demo", 5);
    return 0;
}

正如我所说,在 customer_api.h 下,下面的 CustomerPtr createCustomer(const char* name, int numOrders); 在函数声明 createCustomer 下有波浪线。程序在没有 errors/warnings.

的情况下编译并 运行 成功

也许我没有正确使用 API h 文件概念?我正在尝试对外部文件隐藏客户属性实现,因此在其他文件中,我只在需要访问客户模块时包含 customer_api.h

On one hand it doesn't throw me either error or warning …

您应该在项目设置中启用所有警告;请参阅: 启用警告后,您的代码(或我粘贴到我的 VS 2019 中的代码版本 IDE)会生成 5 个警告:

warning C4255: 'main': no function prototype given: converting '()' to '(void)'
warning C4189: 'customer_p': local variable is initialized but not referenced
warning C4028: formal parameter 2 different from declaration
warning C4267: '=': conversion from 'size_t' to 'int', possible loss of data
warning C4716: 'createCustomer': must return a value

现在,#1、#2、#4可以搁置(暂时);大问题是#3 和#5。

针对 #3:您需要使函数定义中的参数(在“customer.c”中)与原型中的参数(在“customer_api.h”中)相同;据推测,由于结构的 numOrders 成员是 int,您应该将前者更改为具有 int 第二个参数(这也解决并删除了警告 #4):

至地址 #5:createCustomer 函数 必须 return 它向 return 声明的内容: CustomerPtr目的。局部变量 newCustomer_p 是最明显的候选者。

这是该函数的 'fixed' 版本:

CustomerPtr createCustomer(const char* name, int numOrders)
{
    CustomerPtr newCustomer_p = NULL;
    if (customersCount < MAX_NO_OF_CUSTOMERS) {
        newCustomer_p = objectPool + (customersCount++);
        newCustomer_p->name = name;
        newCustomer_p->numOrders = numOrders;
    }
    return newCustomer_p;
}

这留下了警告 #1 和 #2。要修复 #1,添加 void 作为 main 的参数列表(空括号实际上并不 define C 中的函数)。据推测,你会在某个时候对未使用的变量做一些事情,所以这将解决#2。

int main(void) // Note the EXPLICIT void argument list; () just means "unspecified" in C
{
    CustomerPtr customer_p = createCustomer("Demo", 5);
    // Do something with "customer_p"
    (customer_p);
    return 0;
}

… but on the other hand it marks me with a green squiggling.

将鼠标悬停在曲线上会显示问题:“找不到 'createCustomer' 的函数定义。”这是由生成警告 #3 的问题引起的;解决绿色波浪线的修复。

要在客户端模块中隐藏类型 Customer 的实现,您需要将结构定义放在 C 文件中。这是一种方法。在下面的代码中,我简单地调用 CustomerPtr Customer 因为我认为它更简洁。为了简单和一致,最好使用与客户数据类型相同的客户实现和头文件名称。我还建议为 Customer.h 中的每个函数使用前缀 Customer_。我还做了一些其他的调整。

Customer.h

#ifndef CUSTOMER_H
#define CUSTOMER_H

#include <stdlib.h>

typedef struct CustomerDesc *Customer;

Customer Customer_Create(const char *name, size_t numOrders);

#endif

Customer.c

#include "Customer.h"

#define LEN(array) (sizeof (array) / sizeof (array)[0])

struct CustomerDesc {
    unsigned int customerId;
    const char *name;
    int numOrders;
};

static struct CustomerDesc objectPool[10];
static unsigned int customersCount = 0;

Customer Customer_Create(const char *name, size_t numOrders)
{
    Customer newCustomer = NULL;
    if (customersCount < LEN(objectPool)) {
        newCustomer = objectPool + customersCount;
        newCustomer->name = name;
        newCustomer->numOrders = numOrders;
        customersCount++;
    }
    return newCustomer;
}

main.c

#include "Customer.h"

int main(void)
{
    Customer customer = Customer_Create("Demo", 5);
    return 0;
}