Распределить структуру в другой функции в c - PullRequest
1 голос
/ 04 октября 2019

как я могу выделить память для структуры в другой функции, чем где объявлена ​​структурная переменная?

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
argIP: (null)

Но я ожидал (и хочу):
arg IP: 12.21.51.88
arg IP: 12.21.51.88

Ответы [ 2 ]

1 голос
/ 04 октября 2019

Обнаружение ошибки

Это утверждение в main:

mal(argc, argv, &args);

говорит о необходимости передачи адреса от args до mal. Тип args равен 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.

Размещение объявления в заголовочном файле и включение этого файла в каждый исходный файл является лучшим решением, чем копирование объявления в каждый исходный файл, поскольку он обеспечиваетИсходный файл использует ту же декларацию. И включение предупреждений компилятора - и обращая на них внимание - обеспечивает полную цепочку проверки типов - использование mal в main связано с его объявлением, а его объявление связано с его определением. Это позволяет компилятору выполнять всю проверку типов.

Исправление ошибки

Один из способов исправить ошибку - сделать так, чтобы определение mal соответствовало тому, как вы его называете в main,Для этого измените определение mal, чтобы args имел тип ARGS **:

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

Затем внутри, mal, так как тип args изменился, вам нужноиспользовать *args для ссылки на ARGS *, который main передал ему:

*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;

Другие примечания

In 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);

Таким образом, размер выделяемого объекта используется автоматически - если последующие изменения в коде изменяют тип, где объявляется args или args->IP_req, эти выражения автоматически используют новый размер. Необходимо изменить тип в двух или более местах (по одному в объявлении и по одному в каждом malloc).

1 голос
/ 04 октября 2019

Как указано в комментариях @PaulOgilvie, последний аргумент 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); правильный.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...