Всегда ли безопасен sizeof (<type>) вместо sizeof (<variable>)? - PullRequest
2 голосов
/ 02 июня 2019

Я знаю, что могу защитить себя, написав

int *ptr = malloc(sizeof (*ptr))

вместо

int *ptr = malloc(sizeof (int))

Преимущество состоит в том, что если вы решите изменить тип ptr, напримерlong* вместо int*, тогда вам нужно всего лишь изменить код в одном месте.

Мой вопрос: всегда ли безопасна эта стратегия?Есть ли ситуации, когда конструкция T *ptr = malloc(sizeof(*ptr)) не будет работать?Имеет ли значение, если T - это какая-то сложная структура, указатель на указатель, указатель на функцию или массив?Или их комбинация.

Я пытался придумать ситуацию, когда это вызывает проблемы, но мне кажется, что это безопасно.Но я хочу полностью доверять коду.

Ответы [ 2 ]

2 голосов
/ 02 июня 2019

Единственный случай, который может вызвать проблемы, - это если *ptr имеет тип массива переменной длины, потому что это единственный случай, когда sizeof вычисляет свой операнд.

То есть:

int n = ...;
T (*ptr)[n] = malloc(sizeof *ptr);

имеет неопределенное поведение, потому что тип *ptr равен T [n], который является типом массива переменной длины, что означает, что sizeof оценивает его операнд, который разыменовывает неинициализированный указатель (*ptr).

Однако случайно столкнуться с этой проблемой сложно.Обычно вы просто делаете

T *ptr = malloc(n * sizeof *ptr);

, что хорошо 1 .


1 Что ж, умножение может быть переполнено.Чтобы защититься от этого, вам нужно что-то вроде T *ptr = calloc(n, sizeof *ptr);.

0 голосов
/ 02 июня 2019

Это безопасно, портативно и считается хорошей практикой.

Конечно, будет небезопасно, если кто-то скроет указатели в typedefs и сделает код нечитаемым. Но это считается очень плохой практикой.

Указатели на функции очень специфичны, так как им не требуется память для объекта (функции)

...