Так, час дії локальної змінної знаходиться в межах області ( {
, }
), в якій вона створюється.
Локальні змінні мають автоматичне або локальне зберігання. Автоматичні, оскільки вони автоматично знищуються, коли область дії, в якій вони створені, закінчується.
Однак те, що ви маєте тут, - це рядковий літерал, який виділяється у визначеній реалізацією пам’яті лише для читання. Рядкові літерали відрізняються від локальних змінних, і вони залишаються живими протягом усього терміну роботи програми. Вони мають статичну тривалість життя [Посилання 1] .
Слово обережності!
Однак зауважте, що будь-яка спроба змінити вміст рядкового літералу є невизначеною поведінкою (UB). Користувацьким програмам не дозволяється змінювати вміст рядкового літералу.
Отже, завжди рекомендується використовувати const
час, оголошуючи рядок літералом.
const char*p = "string";
замість,
char*p = "string";
Насправді в C ++ застаріло оголошувати рядковий літерал без, const
хоча і не в C. Однак оголошення рядкового літералу з a const
дає вам ту перевагу, яку компілятори зазвичай дають вам попередження на випадок спроби змінити рядковий літерал у другий випадок.
Зразок програми :
#include<string.h>
int main()
{
char *str1 = "string Literal";
const char *str2 = "string Literal";
char source[]="Sample string";
strcpy(str1,source);
strcpy(str2,source);
return 0;
}
Вихід:
cc1: попередження, що трактуються як помилки
prog.c: У функції 'main':
prog.c: 9: error: передавання аргументу 1 'strcpy' відкидає кваліфікатори від типу цільового покажчика
Зверніть увагу, що компілятор попереджає про другий випадок, але не про перший.
Щоб відповісти на питання, яке задають кілька користувачів тут:
Яка справа з інтегральними літералами?
Іншими словами, чи дійсний наступний код?
int *foo()
{
return &(2);
}
Відповідь полягає в тому, що цей код не є дійсним. Він неправильно сформований і видасть помилку компілятора.
Щось на зразок:
prog.c:3: error: lvalue required as unary ‘&’ operand
Рядкові літерали є значеннями l, тобто: Ви можете взяти адресу рядкового літералу, але не можете змінити його вміст.
Тим НЕ менше, будь-які інші литералов ( int
, float
, char
, і т.д.) є г-значення (стандарт С використовує термін значення виразу для них) і їх адреси не можуть бути прийняті на всіх.
[Посилання 1] Стандарт C99 6.4.5 / 5 "Рядові літерали - семантика":
У фазі перекладу 7 байт або код значення нуль додається до кожної багатобайтової послідовності символів, що є результатом рядкового літералу або літералів. Потім багатобайтова послідовність символів використовується для ініціалізації масиву статичної тривалості та довжини сховища, достатньої для вміщення послідовності . Для літеральних рядкових символів елементи масиву мають тип char і ініціалізуються окремими байтами багатобайтової послідовності символів; для широких рядкових літералів елементи масиву мають тип wchar_t і ініціалізуються послідовністю широких символів ...
Не визначено, чи відрізняються ці масиви за умови, що їх елементи мають відповідні значення. Якщо програма намагається змінити такий масив, поведінка не визначена .
int rc
. Його термін служби закінчується на кожному з-return
х. Покажчики, які ви повертаєте, стосуються рядкових літералів. Рядкові літерали мають статичну тривалість зберігання: тривалість життя принаймні така, як у програми.