У меня возникают проблемы с пониманием преобразования типов "указатель на".Позвольте мне привести несколько примеров:
struct test{
int x;
int y;
};
1.
void *ptr = malloc(sizeof(int));
struct test *test_ptr = ptr; //OK 7.22.3(p1)
int x = test_ptr -> x; //UB 6.2.6.1(p4)
2.
void *ptr = malloc(sizeof(struct test) + 1);
struct test *test_ptr = ptr + 1; //UB 6.3.2.3(p7)
3.
void *ptr = malloc(sizeof(struct test) + 1);
struct test *test_ptr = ptr; //OK 7.22.3(p1)
int x = test_ptr -> x; //Unspecified behavior or also UB?
Мое пониманиеслучаев:
- Преобразование указателя, возвращаемое
malloc
, само по себе нормально, как 7.22.3 (p1):
Указатель возвращается, еслираспределение успешно выровнено соответствующим образом, так что его можно назначить указателю на любой тип объекта с фундаментальным требованием выравнивания
Доступ неверен, поскольку test_ptr
не может указывать на действительный struct test_ptr
объект, так как его размер меньше размера, выделенного с malloc
, вызывая UB, как описано в 6.2.6.1 (p4).
Это UB, так как мы ничего не можем сказать о выравнивании указателя
ptr + 1
.6.3.2.3 (p7) объясняет это:
Указатель на тип объекта может быть преобразован в указатель на другой тип объекта.Если полученный указатель неправильно выровнен68) для ссылочного типа, поведение не определено.
Как в стандарте объясняется случай 3 *
Itне указано в стандарте (по крайней мере, я не смог найти), если это действительно для преобразования указателя на объект без объявленного типа в указатель на объект, размер которого меньше, чем один выделенный объект имеет?(Я не рассматриваю распределение массивов здесь, как malloc(10 * sizeof(struct test));
, что ясно объяснено в 7.22.3 (p1)).6.2.6.1 (p4) состояния:
Значения, хранящиеся в объектах без битового поля любого другого типа объекта, состоят из n × CHAR_BIT битов, где n - размер объекта этого типа,в байтах.
Выделенный объект не состоит из sizeof(struct test) x CHAR_BIT
битов, но (sizeof(struct test) + 1) x CHAR_BIT