Передача структуры по ссылке и манипулирование ею - PullRequest
0 голосов
/ 28 ноября 2009
typedef struct unit_class_struct {
    char *name;
    char *last_name;
} person;


int setName(person *array) {

    array[0].name = strdup("Bob");
    array[1].name = strdup("Dick");

    return 1;
}

int setLastName(person *array) {

    array->last_name = strdup("Sanchez");
    array++;
    array->last_name = strdup("Clark");

    return 1;
}

int main()
{
    person array[10];
    person *pointer;
    pointer = array;
    setName(pointer);
    setLastName(pointer);
    printf("First name is %s %s\n", array[0].name, array[0].last_name);
    printf("Second name is %s %s\n", array[1].name, array[1].last_name);
    while(1) {}
    return 0;
}

Это пример кода, который я придумал, чтобы поиграть со структурами. Обратите внимание, как я установил имя в setName и как я это сделал в setLastName.

Обе работы, но мне любопытно, в чем разница между двумя способами, которыми я это сделал?

Один путь лучше, чем другой?

Также необходим ли strdup в этом примере? Если нет, было бы необходимо, если бы я устанавливал array.name для переменных случайного размера, а не для строковых литералов?

Ответы [ 4 ]

1 голос
/ 28 ноября 2009

Если вы установите все ваши .name в строковые константы, то нет, strdup не требуется строго. Вы захотите, если вы собираетесь изменить строку позже. Лучшее заземление в управлении указателем и памятью сделает различие ясным. Если вы используете strdup, обязательно free результат позже.

1 голос
/ 28 ноября 2009

Оба варианта довольно рискованны, потому что вы не знаете длину массива. Следовательно, доступ к результату array ++ или array [1] может привести к неопределенному поведению.

Возможно, вы могли бы попробовать это приложение

int set_last_name(person* array, char* lastnames[],size_t amount){
    int i=0;

    for(;i<amount;i++,array++){
      strncpy(array->lastname,lastnames[i],strlen(lastnames[i]));
    }

     return 1;
 }

где сумма - длина массива фамилий.

Обратите внимание, что нет использования strdup. Эта функция ожидает, что пользователь выделит память для фамилий и массивов. Затем пользователь должен освободить эту память, если это необходимо. Мне не нравится strdup, потому что он возвращает выделенную кучу строку, и в случае ваших функций должно быть четко задокументировано, что пользователь функций должен ее освободить.

0 голосов
/ 28 ноября 2009

array->name точно так же, как (*array).name.

В обеих ваших функциях "массив" является указателем на структуру, поэтому *array и array[0] являются структурами, и вы можете устанавливать их члены. Обозначение стрелки является просто часто используемым сочетанием клавиш.

0 голосов
/ 28 ноября 2009

Использование индексированного подхода немного яснее, чем использование арифметики с указателями, на мой взгляд, но любой из них работает. Я подозреваю, что код, сгенерированный компилятором для каждого из них, очень похож в обоих случаях.

strdup необходимо в этом случае, если вы работаете с переменными, потому что вы не выделяете память для сохранения ваших строковых значений в структуре person. Если вы уже выделили место для этих строк при вызове любого из ваших сеттеров, strcpy (strcpy_s, предпочтительно) будет достаточно.

При работе с литералами, как в вашем примере, strdup не требуется: вы можете назначить напрямую char*.

...