2
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.

1
  • Pay close attention to the error. It has nothing to do with the nested structs you're referring to. You're trying to assign a const pointer to a non-const pointer. Commented Feb 11, 2018 at 4:05

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Ah! Yes the function I'm in had the declaration and parameters given to me. It is a const char*. I am supposed to use the name that is passed to populate the name variable in the symbol struct and later modify it which seems strange when the const is given. Here's the function declaration: int symbol_add (sym_table_t* symTab, const char* name, int addr)
@Bonfire184 a const char* as a function argument is also a hint to the caller that the function won't modify the memory pointed to by the argument, so it's safe to call it with a string literal. In such cases it's best to do a copy of the const char*.
1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.