На языке C показан фрагмент: char *s = "hello"; s[0] = 'H'; Объясните, почему это UB на многих платформах, как правильно изменить строку и какие альтернативы предлагает язык C в подобных ситуациях
Коротко и по делу. Почему это UB: - В коде char *s = "hello"; s[0]=′H′;s[0] = 'H';s[0]=′H′;
строка "hello" — строковый литерал, размещается в статической памяти и на многих платформах — в сегменте только для чтения (.rodata). По стандарту C попытка изменить содержимое строкового литерала — неопределённое поведение (UB). На некоторых реализациях это приведёт к аварийному завершению (segfault), на других — может «сработать» случайно, но это не гарантировано. Как правильно изменить строку: - Использовать автоматический массив (копию литерала): char s[] = "hello"; s[0]=′H′;s[0] = 'H';s[0]=′H′; // легально - Выделить память динамически и скопировать: char *s = malloc(strlen("hello")+1strlen("hello")+1strlen("hello")+1); strcpy(s, "hello"); s[0]=′H′;s[0] = 'H';s[0]=′H′; free(s); - В POSIX можно использовать strdup: char *s = strdup("hello"); s[0]=′H′;s[0] = 'H';s[0]=′H′; free(s); Альтернативы и рекомендации в C: - Если строка не должна изменяться, помечайте её как const: const char *s = "hello"; // компилятор предупредит при попытке записи - Для изменяемых строк — всегда держите модифицируемую копию (массив или malloc). - Для удобства и безопасности используйте библиотечные функции (strdup/strcpy/strncpy) или собственные обёртки управления памятью. Суть: строковый литерал нельзя надежно модифицировать — делайте копию (массив или динамическая память) или объявляйте указатель const.
Почему это UB:
- В коде
char *s = "hello";
s[0]=′H′;s[0] = 'H';s[0]=′H′; строка "hello" — строковый литерал, размещается в статической памяти и на многих платформах — в сегменте только для чтения (.rodata). По стандарту C попытка изменить содержимое строкового литерала — неопределённое поведение (UB). На некоторых реализациях это приведёт к аварийному завершению (segfault), на других — может «сработать» случайно, но это не гарантировано.
Как правильно изменить строку:
- Использовать автоматический массив (копию литерала):
char s[] = "hello";
s[0]=′H′;s[0] = 'H';s[0]=′H′; // легально
- Выделить память динамически и скопировать:
char *s = malloc(strlen("hello")+1strlen("hello")+1strlen("hello")+1);
strcpy(s, "hello");
s[0]=′H′;s[0] = 'H';s[0]=′H′;
free(s);
- В POSIX можно использовать strdup:
char *s = strdup("hello");
s[0]=′H′;s[0] = 'H';s[0]=′H′;
free(s);
Альтернативы и рекомендации в C:
- Если строка не должна изменяться, помечайте её как const:
const char *s = "hello"; // компилятор предупредит при попытке записи
- Для изменяемых строк — всегда держите модифицируемую копию (массив или malloc).
- Для удобства и безопасности используйте библиотечные функции (strdup/strcpy/strncpy) или собственные обёртки управления памятью.
Суть: строковый литерал нельзя надежно модифицировать — делайте копию (массив или динамическая память) или объявляйте указатель const.