【问题标题】:Allocate structure in another function in c在c中的另一个函数中分配结构
【发布时间】:2020-02-02 16:58:29
【问题描述】:

如何在另一个函数中为结构分配内存,而不是在哪里声明结构变量?

typedef struct{
    char *IP_req;
} ARGS;

int main(int argc , char *argv[]){
    ARGS *args = NULL;
    mal(argc, argv, &args);
    printf("arg IP:%s\n", &args->IP_req);
    return 0;
}

我要分配的函数:

int mal(int argc , char *argv[], ARGS *args){
    args=malloc(sizeof (ARGS));
    args->IP_req = (char*)malloc(sizeof(char) * 200);
    strcpy(args->IP_req,"12.21.51.88");
    printf("arg IP:%s\n", args->IP_req);
    return 0;
}

当我编译这个程序时,我得到:
arg IP:12.21.51.88
arg IP:(null)

但我期望(并且想要):
arg IP:12.21.51.88
arg IP:12.21.51.88

【问题讨论】:

  • mal 是什么? ARGS 是什么?
  • mal 代表 malloc,ARGS 是程序参数。我将程序减少到最低限度...
  • 打开编译器警告:ARGS *args 必须是 ARGS **args,然后是 *args=malloc(sizeof (ARGS));
  • 抱歉,我忘记包含我的结构 (ARGS)。我编辑了帖子,请看...
  • 解释:通过&args传递变量的地址,所以函数必须取消引用它以将分配的内存放入变量中。

标签: c function malloc dynamic-memory-allocation


【解决方案1】:

发现错误

main中的这句话:

mal(argc, argv, &args);

表示将args 的地址传递给malargs 的类型是ARGS *,所以&args 的类型是ARGS **

mal的这个定义:

int mal(int argc , char *argv[], ARGS *args)

表示args 参数的类型为ARGS *。由于main 传递的是ARGS **,而不是ARGS *,因此这是一个错误。

如果您正确使用编译器,它应该会警告您以下情况之一:

  • main 中,没有可见的mal 声明。
  • main 中,对mal 的调用与其声明不匹配。
  • mal 的定义与其声明不匹配。

如果编译器没有警告您其中至少一项,那么您需要确保完成两件事:

  • 在编译器中打开或增加警告。如果您通过命令行使用 GCC 或 Clang,请将 -Wall 添加到命令行开关。如果您使用其他接口或其他编译器,请参阅其文档。
  • mal 的声明放在头文件中,并使用#include 将该头文件包含在包含main 的源文件和包含mal 的源文件中。

将声明放在头文件中并将该文件包含在每个源文件中是比将声明复制到每个源文件更好的解决方案,因为它确保每个源文件使用相同的声明。并启用编译器警告——并注意它们——确保有一个完整的链检查类型——mainmal 的使用与其声明相关联,其声明与其定义相关联。这使编译器能够进行所有类型检查。

修复错误

修复错误的一种方法是使mal 的定义与您在main 中的调用方式相匹配。为此,更改mal 的定义以使args 具有ARGS ** 类型:

int mal(int argc , char *argv[], ARGS **args)

那么在里面,mal,由于args的类型发生了变化,你需要使用*args来引用main传递给它的ARGS *

*args = malloc(sizeof (ARGS));
(*args)->IP_req = malloc(sizeof(char) * 200);
strcpy((*args)->IP_req,"12.21.51.88");
printf("arg IP:%s\n", (*args)->IP_req);
return 0;

其他说明

main 中,打印带有%s 的字符串时,不要传递数组的地址,如printf("arg IP:%s\n", &args->IP_req);。使用printf("arg IP:%s\n", args->IP_req); 传递数组第一个元素的地址。 (虽然args->IP_req 最初指的是数组,但在这种情况和大多数情况下,它会自动转换为指向其第一个元素的指针。)

在 C 中(与 C++ 不同),您不需要转换 malloc 的结果,因此 args->IP_req = (char*)malloc(sizeof(char) * 200); 可以只是 args->IP_req = malloc(sizeof(char) * 200);

在计算大小以传递给malloc 时,最好以这种方式使用sizeof

*args = malloc(size **args);
args->IP_req = malloc(200 * sizeof *args->IP_req);

这样,被分配对象的大小会被自动使用——如果以后对代码的编辑改变了声明argsargs->IP_req的类型,这些表达式会自动使用新的大小。有必要在两个或多个位置更改类型(一个在声明处,一个在每个malloc)。

【讨论】:

  • 你是对的,编译器给了我这个:malloc.c:在函数'main'中:malloc.c:11:18:警告:从不兼容的指针类型传递'mal'的参数3 [ -Wincompatible-pointer-types] mal(argc, argv, &args); ^ malloc.c:7:5: 注意:预期为 'ARGS * {aka struct *}' 但参数的类型为 'ARGS ** {aka struct **}' int mal(int argc , char *argv[], ARGS *args); ^~~ 那怎么解决呢??
  • @Eric main 中的 printf 也需要修改。 printf("arg IP:%s\n", args->IP_req);
  • @Eric:我不得不接受你的答案是更好的!但是“调试” OP 的代码很有趣……还有我的代码
【解决方案2】:

正如@PaulOgilvie 在 cmets 中所指出的,mal 的最后一个参数应该是指向指针的指针:

int mal(int argc , char *argv[], ARGS **args) { // **args poits to the pointer to be allocated
    *args = malloc(sizeof (ARGS)); // And all other 'args' herein should be dereferenced
    (*args)->IP_req = (char*)malloc(sizeof(char) * 200);
    strcpy((*args)->IP_req,"12.21.51.88");
    printf("arg IP:%s\n", (*args)->IP_req);
    return 0;
}

您在 main:mal(argc, argv, &args); 中的调用是正确的。

【讨论】:

  • *args->IP_req被解析为*(args->IP_req),但args的类型为ARGS **,所以它是指向指针的指针,而不是指向结构的指针,不能和@987654328一起使用@。正确的代码是(*args)->IP_req,其他带有args 的引用也必须更改。
  • 好的,所以我的回答没有埃里克的那么彻底,但它真的没有用吗?我认为它向 OP 展示了如何解决他/她的问题!
  • 但是你的代码给了我一些错误: malloc.c:18:7: error: ‘args’ is a pointer;你的意思是使用'->'吗? *args->IP_req = (char)malloc(sizeof(char) * 200); ^~ malloc.c:18:7: 错误:'args' 是一个指针;你的意思是使用'->'吗? *args->IP_req = (char)malloc(sizeof(char) * 200); ^~
  • @PetrMarek 查看 Eric 的 cmets,并检查编辑后的代码!抱歉打错了(输入太仓促了)。
  • 好的,我尝试将 *args->IP_req 替换为 (*args)->IP_req ,我确实可以无错误地编译程序,但它仍然没有产生预期的结果。它给了我标准输出:arg IP:12.21.51.88 arg IP:�bR�U(是的,奇怪的字符!)
猜你喜欢
  • 2011-01-19
  • 1970-01-01
  • 2016-02-08
  • 1970-01-01
  • 2021-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多