简体   繁体   中英

Modifying data of nested struct using C

typedef struct node {
  struct node* next;     
  int          hash;     
  symbol_t     symbol;   
} node_t;

typedef struct symbol {
  char* name; 
  int   addr; 
} symbol_t;

Above are the definitions of two structs I am using. I'm trying to add a new node_t to a linked list. First, I allocate memory for the node_t:

node_t* newSymbol = malloc(sizeof(node_t));

Then, the node_t should contain a nested struct (symbol). I try to modify the name property (string) inside the symbol struct that's in the node_t:

newSymbol->symbol.name = name;//name is a parameter to function I'm in

I try to initialize the name and the addr inside of the symbol nested struct; however, I am getting this error:

warning: assignment discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers] newSymbol->symbol.name = name;
                                                                                                                        ^

I've tried multiple ways to modify data in the nested symbol struct, but it either throws the error I listed above or results in a segmentation fault. I'm not sure what I'm doing wrong. Thanks in advance for any help.

name is probably a const char* , symbol->name is a non-const, so the warning tells you that by doing newSymbol->symbol.name = name; you are throwing away the const property and that might not be what you want, as name may be pointing into read-only memory (like a string literal).

This is bad, because if you later do something like this:

newSymbol->symbol.name[0] = toupper(newSymbol->symbol.name[0]);

this could end up with undefined behaviour if newSymbol->symbol points to a read-only location.

Note that with

const char *txt = "Hello";
*txt = 'A';

would give you an error, because of the const .

The solution to this would be the one mentioned by coderredoc: use malloc + strcpy or strdup if available.

newSymbol->symbol.name = strdup(name);
if(newSymbol->symbol.name == NULL)
{
    // error handling
}

or if strdup is not available:

newSymbol->symbol.name = malloc(strlen(name) + 1);
if(newSymbol->symbol.name == NULL)
{
    // error handling
}

strcpy(newSymbol->symbol.name, name);

When you have a function like

void foo(const char *name);

this is also a hint that the function foo won't modify the content pointed to by name , so it's safe to do foo("string literal"); . Because you cannot assume that name points to modifiable memory, it's best to do a copy instead.

You are assigning to a pointer an instance of a local variable. This is not the right thing to do given that local variables lifetime will end when the enclosing block ends. So it will be a dangling pointer to some memory which is in indeterminate state.

Solution is to use strdup like newSymbol->symbol.name = strdup(name); . In case you have not POSIX strdup make one using malloc and memcpy .

newSymbol->symbol.name = malloc(strlen(name)+1);
if(!newSymbol->symbol.name){
    perror("malloc");
    exit(1);
}
memcpy(newSymbol->symbol.name,name, strlen(name)+1);

Also here the error you see is due to completely different reason - it is because you are assigning a const pointer to a non-const variable which is why compiler complained. ( name is a non-const member variable but this error occurred from which it can be inferred that you tried to assign const pointer to this member variable). In this context you can achieve what you are trying to do without removing the const qualifier from the passed argument. How? It is shown in the answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM