6

Consider the following program:

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

typedef struct S_s {
    const int _a;
} S_t;

S_t *
create_S(void) {
    return calloc(sizeof(S_t), 1);
}

void
destroy_S(S_t *s) {
    free(s);
}

const int
get_S_a(const S_t *s) {
    return s->_a;
}

void
set_S_a(S_t *s, const int a) {
    int *a_p = (int *)&s->_a;
    *a_p = a;
}

int
main(void) {
    S_t s1;
    // s1._a = 5; // Error
    set_S_a(&s1, 5); // OK
    S_t *s2 = create_S();
    // s2->_a = 8; // Error
    set_S_a(s2, 8); // OK

    printf("s1.a == %d\n", get_S_a(&s1));
    printf("s2->a == %d\n", get_S_a(s2));

    destroy_S(s2);
}

I'm not aware of anything particularly bad with this kind of design, but there might be impact when compiler is heavily optimizing the code and some considerations I'm missing.

Is it a good idea to use const in C as a mechanism of write access control in such a way?

9

No, using const in such a way is not a good idea.

By declaring your structure fields as const, you are declaring an intention that those fields will never change their value. If you then change the value after all, you are misleading both human readers of your code and the compiler. The first makes the code harder to understand and the second can be the cause for subtle bugs in your program.

If you want to avoid direct access to the members of your structure, then you can just use it as an opaque type:

//in s.h:
typedef struct S_s S_t;

S_t *create_S(void);
void destroy_S(const S_t *s);
int get_S_a(const S_t *s);
void set_S_a(S_t *s, const int a);

//in s.c
#include "s.h"
struct S_s {
    const int _a;
};

S_t *
create_S(void) {
    return calloc(sizeof(S_t), 1);
}

void
destroy_S(const S_t *s) {
    free((S_t *)s);
}

int
get_S_a(const S_t *s) {
    return s->_a;
}

void
set_S_a(S_t *s, const int a) {
    s->_a = a;
}

// In main.c
#include "s.h"
int
main(void) {
    // const S_t s1; // Error: size of S_t unknown here
    S_t *s2 = create_S();
    // s2->_a = 8; // Error: members of S_t unknown here
    set_S_a(s2, 8); // OK

    printf("s2->a == %d\n", get_S_a(s2));

    destroy_S(s2);
}
  • Then I can't create such structures on stack and have arrays of them? – Michael Pankov Dec 27 '13 at 15:46
  • @constantius: That is right. As C does not have proper access control, you have to choose between access protection and the ability to allocate on the stack or in an array. – Bart van Ingen Schenau Dec 27 '13 at 15:56
  • Note I've modified the code so the constness of the structure itself is not used. Also, see securecoding.cert.org/confluence/display/seccode/… and exception EXP05-EX3 in particular. Seems like const fields aren't optimized in any way when the containing structure is not const. Standard reference would be good here. – Michael Pankov Dec 27 '13 at 16:14
  • @constantius: Casting away constness on members also causes undefined behaviour, but is less likely to cause actual problems. A full standard reference would not fit in a comment (If you really want one, ask a new Q for it on StackOverflow.com) – Bart van Ingen Schenau Dec 27 '13 at 16:33
  • So these people writing a secure coding standard are promoting insecure code by making an exception for const-qualification of structure fields? Oh my. – Michael Pankov Dec 27 '13 at 16:38
7

C 2011 draft

6.7.3 Type qualifiers
...
6 If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined. If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined.133)

133) This applies to those objects that behave as if they were defined with qualified types, even if they are never actually defined as objects in the program (such as an object at a memory-mapped input/output address).

Emphasis mine.

So no, this isn't a good idea. If you don't want anyone directly mucking with the contents of your struct type, make it opaque and provide an API to manipulate it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.