How to correctly assign a new string value?

Gianluca Bargelli picture Gianluca Bargelli · Jun 28, 2010 · Viewed 201k times · Source

I'm trying to understand how to solve this trivial problem in C, in the cleanest/safest way. Here's my example:

#include <stdio.h>

int main(int argc, char *argv[])
{
    typedef struct
    {
        char name[20];
        char surname[20];
        int unsigned age;
    } person;

    //Here i can pass strings as values...how does it works?
    person p = {"John", "Doe",30};

    printf("Name: %s; Age: %d\n",p.name,p.age);
    // This works as expected...
    p.age = 25;
    //...but the same approach doesn't work with a string
    p.name = "Jane";

    printf("Name: %s; Age: %d\n",p.name,p.age);

    return 1;
}

The compiler's error is:

main.c: In function ‘main’: main.c:18: error: incompatible types when assigning to type ‘char[20]’ from type ‘char *’

I understand that C (not C++) has no String type and instead uses arrays of chars, so another way to do this was to alter the example struct to hold pointers of chars:

#include <stdio.h>

int main(int argc, char *argv[])
{
    typedef struct
    {
        char *name;
        char *surname;
        int unsigned age;
    } person;

    person p = {"John", "Doe",30};

    printf("Name: %s; Age: %d\n",p.name,p.age);

    p.age = 25;

    p.name = "Jane";

    printf("Name: %s; Age: %d\n",p.name,p.age);

    return 1;
}

This works as expected but I wonder if there a better way to do this. Thanks.

Answer

P&#233;ter T&#246;r&#246;k picture Péter Török · Jun 28, 2010

The first example doesn't work because you can't assign values to arrays - arrays work (sort of) like const pointers in this respect. What you can do though is copy a new value into the array:

strcpy(p.name, "Jane");

Char arrays are fine to use if you know the maximum size of the string in advance, e.g. in the first example you are 100% sure that the name will fit into 19 characters (not 20 because one character is always needed to store the terminating zero value).

Conversely, pointers are better if you don't know the possible maximum size of your string, and/or you want to optimize your memory usage, e.g. avoid reserving 512 characters for the name "John". However, with pointers you need to dynamically allocate the buffer they point to, and free it when not needed anymore, to avoid memory leaks.

Update: example of dynamically allocated buffers (using the struct definition in your 2nd example):

char* firstName = "Johnnie";
char* surname = "B. Goode";
person p;

p.name = malloc(strlen(firstName) + 1);
p.surname = malloc(strlen(surname) + 1);

p.age = 25;
strcpy(p.name, firstName);
strcpy(p.surname, surname);

printf("Name: %s; Age: %d\n",p.name,p.age);

free(p.surname);
free(p.name);