Ограничение преобразования указателя на один тип в указатель на другой тип - PullRequest
0 голосов
/ 18 февраля 2019

У меня возникают проблемы с пониманием преобразования типов "указатель на".Позвольте мне привести несколько примеров:

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?

Мое пониманиеслучаев:

  1. Преобразование указателя, возвращаемое 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

1 Ответ

0 голосов
/ 18 февраля 2019

Это должно быть законно, потому что в C у нас есть члены гибкого массива .

typedef struct flex_s {
  int x;
  int arr[];
} flex_t;
void *ptr = malloc(sizeof(flex_t) + sizeof(int));
flex_t *flex = ptr;
flex->arr[0]; // legal

Так что, если вы хотите получить ответ от стандарта, посмотрите на его определение гибкого массивачленов и их распределение, и будет дано правило.

Вы можете начать, взглянув на пример 20 на стр. 114 из свободного варианта C11 .

...