Home > database >  Copy a string to a *struct member
Copy a string to a *struct member

Time:12-10

I've looked through topics of similar kind, but didn't find a solution for my problem. I've got a struct like

typedef struct {
    int number;
    char *string;
} mystruct;
    
//Then define a pointer to the struct:
mystruct *data;
    
// Allocate memory:
data = malloc(sizeof(mystruct));
    
//Assign some number, let's say 5:
(*data).number = 5;
    
//So far ok, works (checked: 5 can be retrieved from the struct somewhere else) but:
    
strcpy((*data).string = "Hello!");
//This line fails with segmentation fault.

I don't understand why? Can somebody please explain what I'm doing wrong?

CodePudding user response:

As mentioned in the comments, the problem with your attempted strcpy call is that your destination (the string member of your data) isn't a pointer to valid memory. (I am assuming that your invalid syntax, strcpy((*data).string = "Hello!") is a typo, and that your real code has something like strcpy((*data).string, "Hello!") – otherwise, it won't even compile, so you won't get a segmentation fault.)

There are several approaches to fix this, depending on what you actually want to happen. First, as also mentioned in the comments, you can just copy the pointer to the destination, like this1:

data->string = "Hello!";

However, this may not be what you want, because, if the source is not actually a literal, but a modifiable string, then, after that assignment, any changes to the source will also apply to your copy.

If you want a copy of the source data, you will need to allocate sufficient space for it, then call strcpy; like this:

#include <stdlib.h> // For malloc

const char* src = "Hello!";
data->string = malloc(strlen(src)   1); // Add 1 for the required nul-terminator
strcpy(data->string, src);

However, the strdup function2 does the job of the above malloc and strcpy calls in one fell swoop:

data->string = strdup("Hello!");

In each of the above two cases, be sure to call free(data->string) when you're finished.


1 Note that you can use the "member access through pointer" (->) operator, rather than dereferencing and then using the . operator: data->number = 5 is equivalent to your (*data).number = 5.

2 Some compilers/platforms may not support the strdup function, but it is part of the ISO C Standard from C23

CodePudding user response:

I am not sure to understand this line

strcpy((*data).string = "Hello!");

Do you mean

strcpy((*data).string, "Hello!");

I believe the issue is that your struct contain a pointer char * string that doesn't point to a valid allocated memory. You can try multiple solutions

  1. Have struct with predefined size
typedef struct {
    int number;
    char string[100];
} mystruct;

  1. You can allocate memory for the string during the initialization
data = malloc(sizeof(mystruct));
data.string = malloc(sizeof(char) *100));

CodePudding user response:

As other users mentioned, you need to allocate space for the string.

I would use a flexible array member and have only one allocation for the struct and string.

typedef struct {
    int number;
    char string[];
} mystruct;


mystruct *create(const char *str)
{
    mystruct *ms = NULL;

    if(str)
    {
        ms = malloc(sizeof(*ms)   strlen(str)   1);
        if(ms)
        {
            strcpy(ms -> string, str);
            ms -> number = 0;
        }
    }
    return ms;
}

int main(void)
{
    mystruct *ms = create("Hello");

    if(ms)
    {
        printf("ms -> string = `%s`\n", ms -> string);
    }
    free(ms);
}
  • Related