Я ставлю в групу просто, щоб показати несхвалення некрасивого отвору в системі типів, який дозволяє такий код, як наведений нижче фрагмент, збирати без діагностики, хоча жодні касти не використовуються, щоб призвести до поганої конверсії:
double d;
void *p = &d;
int *q = p;
Я б хотів, щоб його не існувало (а його немає в C ++), і тому я виступаю. Це репрезентує мій смак та мою політику програмування. Я не тільки кидаю вказівник, але ефективно, віддаю бюлетень і виганяю демонів дурості . Якщо я насправді не можу вигнати дурість , то, принаймні, дозвольте висловити бажання зробити це жестом протесту.
Насправді, хороша практика полягає в тому, щоб обернути malloc
(і дружити) функціями, які повертаються unsigned char *
, і взагалі ніколи не використовувати void *
у своєму коді. Якщо вам потрібен загальний вказівник на будь-який об’єкт, використовуйте char *
або unsigned char *
і виконайте касти в обох напрямках. Один релаксації , які можна побавитися, можливо, використовує такі функції , як memset
і memcpy
без зліпків.
Що стосується теми кастингу та сумісності C ++, якщо ви пишете свій код так, що він компілюється як C, так і C ++ (у такому випадку вам потрібно передати повернене значення malloc
при призначенні його чомусь іншому, ніж void *
), ви можете зробити дуже корисним Реч для себе: ви можете використовувати макроси для кастингу, які перекладаються на касти у стилі C ++ при компілюванні як C ++, але зменшують до символу C при компілюванні як C:
/* In a header somewhere */
#ifdef __cplusplus
#define strip_qual(TYPE, EXPR) (const_cast<TYPE>(EXPR))
#define convert(TYPE, EXPR) (static_cast<TYPE>(EXPR))
#define coerce(TYPE, EXPR) (reinterpret_cast<TYPE>(EXPR))
#else
#define strip_qual(TYPE, EXPR) ((TYPE) (EXPR))
#define convert(TYPE, EXPR) ((TYPE) (EXPR))
#define coerce(TYPE, EXPR) ((TYPE) (EXPR))
#endif
Якщо ви дотримуєтесь цих макросів, то простий grep
пошук вашої кодової бази за цими ідентифікаторами покаже вам, де всі ваші трансляції, тож ви зможете перевірити, чи не вказано жодне з них.
Тоді, вперед, якщо ви регулярно компілюєте код з C ++, він буде примусово використовувати відповідний склад. Наприклад, якщо ви використовуєте strip_qual
тільки для видалення const
або volatile
, але зміни програми таким чином , що перетворення типу в даний час бере участь, ви отримаєте діагностики, і ви повинні будете використовувати комбінацію зліпків , щоб отримати бажане перетворення.
Щоб допомогти вам дотримуватися цих макросів, компілятор GNU C ++ (не C!) Має прекрасну особливість: додаткову діагностику, яка виробляється для всіх випадків кастингу стилю C.
-Старий стиль (лише C ++ та Objective-C ++)
Попередьте, якщо використовується старий стиль (C-стиль), призначений для недійсного типу
в рамках програми C ++. У ролях нового стилю (dynamic_cast,
static_cast, reinterpret_cast та const_cast) менш вразливі
до ненавмисних ефектів і набагато простіше шукати.
Якщо ваш код C компілюється як C ++, ви можете використовувати цю -Wold-style-cast
опцію, щоб дізнатися про всі виникнення (type)
синтаксису кастингу, які можуть повзати в код, і продовжити цю діагностику, замінивши його відповідним вибором серед вищевказаних макросів (або комбінування, якщо необхідно).
Ця обробка перетворень є найбільшим окремим технічним обгрунтуванням роботи в "чистому С": комбінованому діалекті С і С ++, що, у свою чергу, технічно виправдовує викид зворотного значення malloc
.