3

I am trying to understand why the following code compiles and runs fine. I would expect any assignment using data inside f not to compile with a gcc error assignment of member ‘i’ in read-only object. Is there some kind of exception, because data.i is allocated dynamically?

#include <stdio.h>
#include <stdlib.h>

struct a {
    int *i;
};

void f(const struct a *data) {
    data->i[0] = 55; 
}

int main() {
    struct a data;
    data.i = malloc(2 * sizeof(int));
    
    f(&data);
    
    printf("%d\n", data.i[0]);
    
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
b1000
  • 87
  • 1
  • 7
  • 10
    You are not modifying the pointer but something it points, so there is no problem with this code. – Maxime B. Aug 20 '20 at 09:26
  • 2
    You would get an error if you tried to modify `data->i`, but modifying `data->i[0]` does not change the contents of `data`. If `i` were an array rather than a pointer, then the situation would be different. – Tom Karzes Aug 20 '20 at 09:30
  • @tom-karzes Is there a way to forbid any assignment to a memory location accessed by `data` pointer? – b1000 Aug 20 '20 at 09:35
  • https://stackoverflow.com/questions/890535/what-is-the-difference-between-char-const-and-const-char – nicomp Aug 20 '20 at 09:36
  • 1
    @b1000 You'd need to change the declaration of `i` within the `struct`. – Tom Karzes Aug 20 '20 at 09:39
  • 1
    @b1000 You could declare it as `const int* i;` inside the struct but then you can no longer use malloc, so that would be quite useless in this case. – Lundin Aug 20 '20 at 10:21
  • 1
    Inside `f()` the following applies:`data` is not const; `data->i` is const; `data->i[0]` is not const – pmg Aug 20 '20 at 10:23

3 Answers3

2

const front of a struct will make it read-only. If the struct contains pointer members, then those pointers themselves will turn read-only. Not what they point at.

That is, const struct a will make the member i behave is if it was declared as int *const i;, meaning that the pointer itself cannot be changed to point elsewhere. The pointed-at data is still of read/write int though.

If you want to restrict access to i inside a function, you should make that function take a const int* parameter and pass the i member to that function.

Lundin
  • 195,001
  • 40
  • 254
  • 396
1

In the below code, const indicates what data points to is not to be modified. data->i[0] = 55; does not modify the pointer data->i. Instead that line of code modifies the memory pointed to by data->i. This is allowed as pointer .i is int * and not const int *.

struct a {
    int *i;
};

void f(const struct a *data) {
    data->i[0] = 55; 
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

You cant modify i but you can modify the objects referenced by i.

To prevent it you need to:

struct a {
    const int *i;
};
0___________
  • 60,014
  • 4
  • 34
  • 74