Причиною цієї проблеми (яку навіть важче виявити, ніж проблему, char* str = "some string"
- з якою пояснили інші), є коли ви використовуєте constexpr
.
constexpr char* str = "some string";
Здається, він би поводився подібним чином const char* str
, і тому не викликав би попередження, як це відбувається раніше char*
, але натомість поводиться так, як char* const str
.
Деталі
Постійний покажчик і вказівник на константу. Різниця між const char* str
і char* const str
може бути пояснена наступним чином.
const char* str
: Оголосити str для вказівника на const char. Це означає, що дані, на які цей вказівник вказує на нього, є постійними. Покажчик може бути модифікований, але будь-яка спроба змінити дані призведе до помилки компіляції.
str++ ;
: ВАЛІДНА . Ми змінюємо вказівник, а не дані, на які вказують.
*str = 'a';
: ІНВАЛІД . Ми намагаємось змінити дані, на які вказували.
char* const str
: Оголосити str для const вказівника на char. Це означає, що ця точка є постійною, але дані, на які вказують, також не є. Вказівник неможливо змінити, але ми можемо змінити дані за допомогою вказівника.
str++ ;
: ІНВАЛІД . Ми намагаємось змінити змінну вказівника, яка є постійною.
*str = 'a';
: ВАЛІДНА . Ми намагаємось змінити дані, на які вказували. У нашому випадку це не призведе до помилки компіляції, але призведе до помилки під час виконання , оскільки рядок, ймовірно, перейде в розділ лише для читання зібраного двійкового файлу. Це твердження мало б сенс, якби ми динамічно виділяли пам'ять, наприклад. char* const str = new char[5];
.
const char* const str
: Оголосити str для const вказівника на const char. У цьому випадку ми не можемо змінити ні вказівник, ні дані, на які вказують.
str++ ;
: ІНВАЛІД . Ми намагаємось змінити змінну вказівника, яка є постійною.
*str = 'a';
: ІНВАЛІД . Ми намагаємось змінити дані, вказані цим вказівником, які також є постійними.
У моєму випадку проблема полягала в тому, що я очікував constexpr char* str
поводитись так const char* str
, як ні char* const str
, оскільки візуально це здається ближчим до колишнього.
Також попередження, створене для constexpr char* str = "some string"
, дещо відрізняється від char* str = "some string"
.
- Попередження компілятора для
constexpr char* str = "some string"
:ISO C++11 does not allow conversion from string literal to 'char *const'
- Попередження компілятора для
char* str = "some string"
: ISO C++11 does not allow conversion from string literal to 'char *'
.
Порада
Ви можете використовувати конвертер C gibberish ↔ English для перетворення C
декларацій у легко зрозумілі англійські твердження та навпаки. Це C
єдиний інструмент, і таким чином не будемо підтримувати речі (наприклад, constexpr), які є ексклюзивними C++
.
strncpy(str, func, 255)
замістьstrcpy(str, func)
безпечнішої копії. І тоді не забудьте додати "\ 0" в кінці рядка, оскільки strncpy не додає його.