【发布时间】:2020-09-09 13:52:27
【问题描述】:
我目前正在学习 C,这也是我在这里的第一个问题。 问题如下。当我尝试编译此代码时收到此警告
#include <stdio.h>
#include "LicenseManager.h"
int main(void)
{
puts("program start");
struct License *license = read();
// other code
}
read() 方法在 LicenseManager.h 中声明为struct License *read(void){...},它返回的指针是对static struct License license; 的引用,但是当我尝试编译时,编译器拒绝并说
警告:函数'read'的隐式声明 [-Wimplicit-function-declaration]
struct License *license = read();
甚至我的 IDE 都说 read();方法返回一个 int (当我在 main 方法中查看它时,在实际的 LicenseManager.h 中,IDE 正确显示 struct License *。
我尝试了什么:
我尝试在主方法上方制作一个方法原型struct License *read(void);
#include <stdio.h>
#include "LicenseManager.h"
struct License read();
int main(void)
{
puts("program start");
struct License *license = read();
// other code
}
,它解决了该错误并获得了要编译的代码,但是现在我立即得到了一个
分段错误
(甚至在调用puts("program start"); 之前)。
我试图将read() 的返回值从一个指向实际结构的指针更改,但这引发了同样的问题。
接下来我尝试将read() 方法更改为void read(struct License *license) 并在外部提供指向对象的指针,但我仍然每次都收到相同的分段错误。在第一行代码被调用之前。
在我尝试了一切之后,我的最终代码现在看起来像这样:
#include <stdio.h>
#include "LicenseManager.h"
void read(struct License *license);
int main(void)
{
puts("program start");
struct License license;
read(&license);
}
不用说。它仍然没有运行。 :(我做错了什么?
所以我发现了一些东西,感谢你们并通过一些测试。 当我使用我的 MingW64(我在 Windows 上运行)控制台时,出现分段错误。我想避免在这里发布大量代码。但我想我会做到的。我使用的库是一个开源 Json 库,名为 cJSON
。 LicenseManager.c
#include <stdio.h>
#include "cJSON.c"
#include "cJSON.h"
#include "LicenseManager.h"
#include <time.h>
#define JSON_FILE "license.json"
void interpret(cJSON *json, struct License *license);
// DEFINE VALUES IN JSON FILE
const char *LICENSE_NAME = "printerLicense";
const char *LICENSE_COMPANY_NAME = "name";
const char *LICENSE_PRINTER_ID = "id";
const char *LICENSE_VALID_START = "validFrom";
const char *LICENSE_VALID_END = "validTo";
const char *LICENSE_PERMISSIONS = "permissions";
const char *LICENSE_HARDWARE_ID = "hardwareId";
//############################
char *readFile(void)
{
FILE *f = fopen(JSON_FILE, "rb");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
rewind(f);
char *string = malloc(fsize + 1);
fread(string, 1, fsize, f);
fclose(f);
string[fsize] = 0;
return string;
}
void parseDate(cJSON *json, struct Date *date)
{
fflush(stdout);
unsigned short valYear, valMonth, valDay;
cJSON *child = json;
valYear = child->valueint;
child = child->next;
valMonth = child->valueint;
child = child->next;
valDay = child->valueint;
date->year = &valYear;
date->month = &valMonth;
date->day = &valDay;
}
void setLicenseRights(cJSON *json, struct License *license)
{
cJSON *rights = get_Array_item(json, LICENSE_PERMISSIONS, cJSON_False);
int size = cJSON_GetArraySize(rights);
char *permissions[size];
for (size_t i = 0; i < size; i++)
{
permissions[i] = get_array_item(rights, i);
}
memcpy(license->permissions, permissions, sizeof(permissions));
}
void interpret(cJSON *json, struct License *license)
{
cJSON *licenseJson = json->child;
struct Date validFrom;
parseDate(get_object_item(licenseJson, LICENSE_VALID_START, cJSON_False), &validFrom);
struct Date validTo;
parseDate(get_object_item(licenseJson, LICENSE_VALID_END, cJSON_False), &validTo);
cJSON *companyName = get_object_item(licenseJson, LICENSE_COMPANY_NAME, cJSON_False);
cJSON *hardwareID = get_object_item(licenseJson, LICENSE_HARDWARE_ID, cJSON_False);
cJSON *printerID = get_object_item(licenseJson, LICENSE_PRINTER_ID, cJSON_False);
setLicenseRights(licenseJson, license);
license->companyName = companyName->valuestring;
license->hardwareID = hardwareID->valuestring;
license->printerID = printerID->valuestring;
license->validFrom = &validFrom;
license->validTo = &validTo;
}
//reads the License file. Use this to read the License.
void read(struct License *license)
{
printf("#####################\n");
fflush(stdin);
char *string = readFile();
printf("#####################\n");
fflush(stdin);
cJSON *json = cJSON_Parse(string);
printf("#####################\n");
fflush(stdin);
interpret(json, license);
printf("#####################\n");
fflush(stdin);
cJSON_Delete(json);
free(string);
}
许可证管理器.h
#ifndef DATE
#define DATE
struct Date
{
unsigned int *year, *month, *day;
};
#endif
#ifndef LICENSE
#define LICENSE
struct License
{
char *companyName;
char *printerID;
char *hardwareID;
struct Date *validFrom;
struct Date *validTo;
char *permissions[];
};
#endif
当然还有 main.c
#include <stdio.h>
#include "LicenseManager.h"
void read(struct License *license);
int main(void)
{
puts("program start");
fflush(stdout);
struct License license;
read(&license);
}
我忘记在我的主文件中包含实际的 LicenseManager.c 文件。现在我得到了一些我可能能够修复的其他编译器错误。所以编译器只是假设 read 方法只返回一个 int,因为没有实际声明它。现在我只需要处理一些不兼容的指针哈哈。
【问题讨论】:
-
原型
struct License read();与您的使用方式不匹配。当您使用它时,您将结果分配给指向License的指针。另请注意,原型表示read的参数是未知的。如果你想说函数不接受参数,那么你需要明确地使用void作为参数类型。 -
还有一个问题是,在 POSIX 系统(如 Linux 或 macOS)上,有一个名为
read的 系统调用,它执行的操作与您的函数不同,以及使用不同的参数。这就是为什么在 C 语言中,通常使用前缀来区分函数。比如license_read. -
问题可能出在您未显示的
read方法中 -
这里缺少最重要的东西:你是如何编译这个的?我怀疑你只是包含了标题,但是如果标头仅包含其签名。您还需要它的定义,它可能在其他一些
.c文件中,需要 与您的一起传递给编译器。 -
@Marco Bonelli -- 你是对的,没有足够的信息。毫无疑问,该功能的实现将需要在链接时进行。但是,在我看来,在到达那个阶段之前事情就出了问题。
标签: c