【问题标题】:struct as return value not compiling/running结构作为返回值不编译/运行
【发布时间】: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


【解决方案1】:

请提供标题代码或至少从那里提取read()并在此处发布完整的程序

使用 3 个版本的 read() 程序

请将下面的代码与您的版本进行比较,并查看可能的线索并询问它们

节目展示

Start
read() as "License read()" 35? : 35
read() as "License* read()" 9? : 9
read() as "void read(License*)" -56? : -56
End

代码

#include <stdio.h>
#include <stdlib.h>

typedef struct { int i; } License;

License* pRead(void);
License read(void);
void readV(License* L);

int main(void)
{
    puts("Start");
    License license = read();
    printf("read() as \"License read()\" 35? : %d\n", license.i);
    License* p = pRead();
    printf("read() as \"License* read()\" 9? : %d\n", p->i);
    free(p);
    readV(&license);
    printf("read() as \"void read(License*)\" -56? : %d\n", license.i);
    puts("End");
    return 0;
};  // main()

License*    pRead()
{
    License* p = (License*)malloc(sizeof(License));
    p->i = 9;
    return p;
};

License read()
{
    License L = { 35 };
    return L;
};

void        readV(License* L) { L->i = -56; };

您的代码的一个小改动:a

    typedef struct { int i; } License;

插入是为了不到处重复关键字struct

【讨论】:

  • 哦,typedef 看起来很方便!我将来一定会使用它。
【解决方案2】:

警告:

警告:函数'read'的隐式声明 [-Wimplicit-function-declaration] struct License *license = read();

告诉您提供的显式原型与您尝试使用的原型不匹配:

struct License read();

此外,如果头文件中提供了这个原型,则不应在源代码中重新声明它。

简单地说,函数read的原型需要匹配其在所示代码中的预期用途:

这是您的代码的改编版本(添加了一些附加内容以帮助在我的系统上构建,即假结构。)

// implementation of sample struct to allow build without "LicenseManager.h"
struct License 
{
    int a;
    int b;
    char account[80];
};

//again, because I do not have "LicenseManager.h", prototype provided here.
struct License *read(void);//corrected prototype

int main(void)
{
    puts("program start");
    struct License *license = read();//this usage dictates prototype needs of read()
    printf("%d\n%d\n%s", license->a, license->b, license->account);
    free(license);//free memory once no longer needed.
    return 0;

}

struct License *read(void)//example implementation but using proper prototype  
{
    struct License *new = malloc(sizeof(*new));//create memory
    //populate struct with some values:
    new->a = 10;
    new->b = 20;
    strcpy(new->account, "Bains");
    return new;
}
       

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    • 1970-01-01
    • 2011-02-28
    • 1970-01-01
    • 2020-12-04
    相关资源
    最近更新 更多