Причиною цієї проблеми (яку навіть важче виявити, ніж проблему, 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 не додає його.