Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to change a const struct member in C?

Tags:

c

I have to change a const member of a const struct instance in C.

I already know it is possible to change a const basic type as follows:

const int a = 2;
*(int*)&a = 3;

I also can change a const member of a struct instance as follows:

typedef struct ST {
  const int a;
  const int b;
}ST;
ST st = {.a = 1,.b =2};

int main() {
    *(int *)(&((*(ST*)(&st)).a)) = 5; //works fine , no problem
}

However i had no success trying to change the const member of the struct instance, if the instance is constant:

typedef struct ST {
  const int a;
  const int b;
}ST;

const ST st = {.a = 2,.b=3}; //const instance

int main() {
    *(int *)(&((*(ST*)(&st)).a)) = 5; //does not work(Seg fault)!!
}

So , would it be possible to change the "a" member value in this last scenario? If not , why?

like image 961
maycon kruger Avatar asked Dec 06 '25 08:12

maycon kruger


2 Answers

I already know it is possible to change a const basic type as follows:

const int a = 2;
*(int*)&a = 3;

The fact that your compiler lets you do it does not make it legal. This code invokes undefined behavior, so the same program could fail or crash if you run it on a different platform, or use a different compiler.

*(int *)(&((*(ST*)(&st)).a)) = 5; //works fine , no problem

This code has the same problem: it invokes undefined behavior.

The last piece of code that you try also has (you guessed it!) undefined behavior. This time, however, the program crashes instead of running to completion.

like image 64
Sergey Kalinichenko Avatar answered Dec 08 '25 22:12

Sergey Kalinichenko


C compilers usually place constants in a read only memory segment, usually called .TEXT or .CODE. This segment (block of memory) is protected against writes by the operating system, or for small embedded CPUs and SoC constants are usually placed in the ROM/ or Flash memory along with the code. What you are trying to do is not recommended, as it would affects all modules using the constant.

Try to change your linking options to generate a map file, if you are interested in the memory segmentation and get a feel as to how the compiler and the linker manage memory.

[EDIT] But you can, in fact, easily change a const member in a const structure, provided the constant is in a writable data segment. You can try this:

int someFunc()
{
    const ST CONST_ONSTACK = { .a = 10, .b = 20 }; // the constant is on the stack...
    *(int*)&(CONST_ONSTACK.a) = 3}
    return CONST_ONSTACK.a;
}

If your compiler is any good, you should get a warning.

like image 23
Michaël Roy Avatar answered Dec 08 '25 21:12

Michaël Roy