views:

121

answers:

4
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;
}

This is some example code I came up with to play around with structures. Notice the way I set the name in setName and the way I did it in setLastName.

Both work, but I'm curious whats the difference between the two ways I did it?

Is one way better than the other?

Also is strdup necessary in this example? If not, would it be necessary if I was setting array.name to random sized variables rather than string literals?

A: 

Using the indexed approach is slightly clearer than using the pointer arithmetic, in my opinion but either works. I suspect the code the compiler generates for each is quite similar in both instances.

strdup is necessary in this instance if you're working with variables because you do not allocate memory to save your string values in in the person struct. If you'd already allocated space for those strings when either of your setters was called, strcpy (strcpy_s, preferably) would be sufficient.

When working with literals as you are in your example, strdup is not necessary: you can assign directly to the char*.

antik
+1  A: 

If you set all your .name's to string constants, then no, strdup is not strictly needed. You'll want it if you're going to modify the string later. A better grounding in pointer's and memory management will make the distinction clear. If you do use strdup, be sure to free the result later.

Thanatos
+1  A: 

Both options are quite risky, because you don´t know the length of the array. Consequently, accessing the result of array++ or array[1] could result in undefined behaviour.

Perhaps you could try this apprach

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

where amount is the length of the lastnames array.

Note that theres no usage of strdup. This function would expect the user to allocate memory for lastnames and array. Then the user should free that memory , if needed. I dislike strdup because it returns a heap allocated string, and in the case of your functions, it should be clearly documented that the user of the functions has to free it.

Tom
A: 

array->name is exactly the same as (*array).name.

In both your functions "array" is a pointer to a structure, so both *array and array[0] are structures, and you can set their members. The arrow notation is just a often used shortcut.

pmg