Правильность const для структур с указателями
У меня есть структура, которая содержит несколько указателей. Я хочу, чтобы их значение не изменялось. Но простое написание const infront не делает членов структуры неизменными
typedef struct{
int *x;
int *y;
}point;
void get(const point *p,int x, int y){
p->x[0]=x;//<- this should not be allowed
p->y[0]=y;//<- this should not be allowed
}
Может кто-нибудь направить меня в правильном направлении.
РЕДАКТИРОВАТЬ:
Поэтому может показаться, что не существует простого способа использования прототипа функции, чтобы сказать, что все, что принадлежит структуре, должно быть неизменяемым.
4 ответа
Чтобы объяснить, что вам нужно установить, когда вы пишете
point str;
point *p=&str;
Здесь p - указатель на str типа точка
Когда вы объявляете его как const, это означает, что p является постоянным указателем. Это не ограничивает указатели, которые может содержать структура.
Если вы хотите const
Чтобы применить внутри структуры, вы должны определить указатели внутри структуры также как const
typedef struct{
const int * x;
const int * y;
}point;
Снова, чтобы подтолкнуть домой мою точку объявить параметр как
void get(point * const p,int x, int y)
//Constant Pointer ( *to prevent p from pointing to anything else*)
// AND
//Make the pointers inside point structure constant
//( *to prevent the int pointers x & y from pointing to anything else*)
Если структура, на которую она указывает, также является постоянным
void get(const point * const p, int x, int y)
//Constant Pointer to constant structure
Вы можете сделать это без приведения типов, определив тип константной точки и тип изменяемой точки, а затем использовать прозрачное объединение:
typedef struct{
const int * x;
const int * y;
} const_point;
typedef struct{
int * x;
int * y;
} mutable_point;
typedef union __attribute__((__transparent_union__)) {
const_point cpoint;
mutable_point point;
} point;
Затем вы объявляете параметры своей функции, используя тип point или const_point (никогда не тип mutable_point).
объект типа point будет прозрачно приведен к типу const_point, но не наоборот. Это позволяет вам иметь большую степень безопасности типов.
Смотрите здесь для примера в gcc: http://toves.freeshell.org/xueg/
Обратите внимание, что прозрачное объединение не поддерживалось в последней версии C++, которую я проверял (не уверен насчет последнего стандарта C++), поэтому вы можете ожидать проблем с переносимостью.
Это также может затруднить чтение и поддержку кода, особенно если у вас более сложная структура. Например: у вас может быть тип точки, где x или y является константой, или вам может потребоваться встроить структуру точек в другую структуру, например, прямоугольник, для которого вам может потребоваться определить несколько структур для нескольких типов в зависимости от их константности.
В общем, я не уверен, что это всегда стоит дополнительных хлопот.
Если я правильно понимаю ваш вопрос, вы хотели бы получить автоматическое распространение константности всего объекта структуры на объекты, указанные членами этой структуры. Т.е. если объект структуры не является константным, массивы должны быть модифицируемыми, в то время как, если объект структуры является константными, массивы не должны быть модифицируемыми.
Если так, то, к сожалению, это не достижимо на языке Си.
В C++ это можно сделать, заставив пользователя использовать функцию-член accessor для доступа к элементам данных (вместо прямого доступа к элементам данных). Но в Си это просто невозможно сделать.
Это потому, что вы меняете содержимое памяти, на которое указывает другой указатель, чем p
,
p
указывает на структуру, содержащую 2 указателя на int
, Вы не меняете память p
указывает на другую область памяти. Таким образом, компилятор в порядке с этим.
+----------+
p -> | x | -> wherever
+----------+
| y | -> another place in memory
+----------+
const
Ness Od p
не наследуется Если бы вы написали p->a = array;
тогда компилятор жаловался бы. const
это всего лишь контракт, в котором говорится, что вы не измените память через этот указатель.