Переглядаючи код, я застосовую такі правила:
Завжди використовуйте const
параметри функції, передані посиланням, коли функція не змінює (або звільняє) вказані дані.
int find(const int *data, size_t size, int value);
Завжди використовуйте const
для констант, які в іншому випадку можна визначити за допомогою #define або enum. У результаті компілятор може знайти дані в пам'яті лише для читання (ROM) (хоча лінкер часто є кращим інструментом для цієї мети у вбудованих системах).
const double PI = 3.14;
Ніколи не використовуйте const у прототипі функції для параметра, переданого за
значенням . Це не має жодного значення, а значить, просто "шум".
// don't add const to 'value' or 'size'
int find(const int *data, size_t size, const int value);
Якщо потрібно, використовуйте const volatile
місця, які не можуть бути змінені програмою, але можуть все-таки змінитися. Типові випадки використання тут є регістри обладнання, наприклад, регістр стану, який відображає стан пристрою:
const volatile int32_t *DEVICE_STATUS = (int32_t*) 0x100;
Інші способи використання необов’язкові. Наприклад, параметри функції в рамках реалізації функції можуть бути позначені як const.
// 'value' and 'size can be marked as const here
int find(const int *data, const size_t size, const int value)
{
... etc
або функціонувати повернені значення або обчислення, які отримуються, а потім ніколи не змінюються:
char *repeat_str(const char *str, size_t n)
{
const size_t len = strlen(str);
const size_t buf_size = 1 + (len * n);
char *buf = malloc(buf_size);
...
Ці використання const
просто означають, що ви не зміните змінну; вони не змінюють, як і де зберігається змінна. Звичайно, компілятор може виявити, що змінна не змінюється, але додавши const
Ви дозволяєте їй це застосувати. Це може допомогти читачеві та додати певну безпеку (хоча якщо ваші функції досить великі або складні, що це має велику різницю, у вас, певно, є інші проблеми). Редагувати - наприклад. 200-рядкова щільно кодована функція з вкладеними циклами та багатьма довгими або подібними назвами змінних, знаючи, що певні змінні ніколи не змінюються, може полегшити розуміння. Такі функції були погано розроблені або підтримувані.
Проблеми з const
. Ви, ймовірно, почуєте термін "отруєння const". Це відбувається, коли додавання const
до параметра параметра викликає поширеність «constness».
Редагувати - отруєння const: наприклад у функції:
int function_a(char * str, int n)
{
...
function_b(str);
...
}
якщо ми переходимо str
до цього const
, ми повинні переконатися, що це fuction_b
також займає const
. І так далі, якщо function_b
переходить str
на і function_c
т. Д. Як ви можете уявити, це може бути болісно, якщо воно поширюється на безліч окремих файлів / модулів. Якщо він поширюється на функцію, яку неможливо змінити (наприклад, системну бібліотеку), тоді необхідний додаток. Тож розсипання
const
існуючого коду, можливо, вимагає неприємностей. Однак у новому коді найкраще const
послідовно класифікувати, де це доречно.
Більш підступною проблемою const
є те, що це було не мовою оригіналу. Як доповнення він не зовсім підходить. Для початку це має два значення (як у правилах вище, тобто "я не збираюся цього змінювати" і "це неможливо змінити"). Але більше того, це може бути небезпечно. Наприклад, компілюйте та запустіть цей код і (залежно від компілятора / параметрів) він може збитися під час запуску:
const char str[] = "hello world\n";
char *s = strchr(str, '\n');
*s = '\0';
strchr
повертає a char*
не a const char*
. Як його параметр виклику,
const
він повинен передавати параметр виклику char*
. І в цьому випадку це відкидає реальну властивість зберігання лише для читання. Редагувати: - це стосується, як правило, варіантів пам’яті лише для читання. Під «ROM» я маю на увазі не просто фізичний ПЗУ, а будь-яку пам'ять, захищену від запису, як це відбувається з кодовим розділом програм, що працюють у типовій ОС.
Багато стандартних функцій бібліотеки поводяться однаково, тому будьте обережні: коли у вас є реальні константи (тобто, що зберігаються в ПЗУ), ви повинні бути дуже обережними, щоб не втратити їхню стійкість.
Specific issues with software development
. Я досить конкретний.