Spec-Zone.ru › C

Литералы строк

Создаёт анонимный объект указанного типа массива символов на месте, используется, когда строка символов должна быть встроена в исходный код.

Синтаксис

" Последовательность символов s " (1)
u8" Последовательность символов s " (2) (с C11)
u" Последовательность символов s " (3) (с C11)
U" Последовательность символов s " (4) (с C11)
L" Последовательность символов s " (5)

где

Последовательность символов s - ноль или более символов, каждый из которых является многобайтовым символом из набора символов исходного кода (исключая ("), \, и символ новой строки), или escape-последовательность, шестнадцатеричная escape-последовательность, восьмеричная escape-последовательность, или универсальное имя символа(с C99), как определено в escape-последовательностях.
1) литерал строки символов: Тип литерала — char[N], где N — размер строки в кодовых единицах выполнения узкой кодировки, включая нулевой терминатор. Каждый элемент char массива инициализируется следующим символом в Последовательности символов s с использованием набора символов выполнения.
2) литерал строки UTF-8: Тип литерала — char[N](до C23)char8_t[N](с C23), где N — размер строки в кодовых единицах UTF-8, включая нулевой терминатор. Каждый элемент char(до C23)char8_t(с C23) массива инициализируется следующим многобайтовым символом в Последовательности символов s с использованием кодировки UTF-8.
3) 16-битный литерал строки с широким символом: Тип литерала — char16_t[N], где N — размер строки в кодовых единицах реализации 16-битной кодировки (обычно UTF-16), включая нулевой терминатор. Каждый элемент char16_t массива инициализируется, как если бы выполнялось mbrtoc16 в реализации локали. 4) 32-битный литерал строки с широким символом: Тип литерала — char32_t[N], где N — размер строки в кодовых единицах реализации 32-битной кодировки (обычно UTF-32), включая нулевой терминатор. Каждый элемент char32_t массива инициализируется, как если бы выполнялось mbrtoc32 в реализации локали. (до C23)
3) литерал строки UTF-16: Тип литерала — char16_t[N], где N — размер строки в кодовых единицах UTF-16, включая нулевой терминатор. Каждый элемент char16_t массива инициализируется следующим многобайтовым символом в Последовательности символов s с использованием кодировки UTF-16. 4) литерал строки UTF-32: Тип литерала — char32_t[N], где N — размер строки в кодовых единицах UTF-32, включая нулевой терминатор. Каждый элемент char32_t массива инициализируется следующим многобайтовым символом в Последовательности символов s с использованием кодировки UTF-32. (с C23)
5) литерал строки с широким символом: Тип литерала — wchar_t[N], где N — размер строки в кодовых единицах выполнения широкой кодировки, включая нулевой терминатор. Каждый элемент wchar_t массива инициализируется, как если бы выполнялось mbstowcs в реализации локали.

Объяснение

Во-первых, на стадии трансляции 6 (после подстановки макросов), смежные строковые литералы (то есть строковые литералы, разделённые только пробелами) конкатенируются.

Можно конкатенировать только два узких или два широких строковых литерала.

(до C99)

Если один литерал не имеет префикса, результирующий строковый литерал имеет ширину/кодировку, указанную префиксным литералом.

L"Δx = %" PRId16 // at phase 4, PRId16 expands to "d"
                 // at phase 6, L"Δx = %" and "d" form L"Δx = %d"
(с C99)

Если два строковых литерала имеют разные префиксы кодировки, конкатенация определяется реализацией, за исключением того, что строковый литерал UTF-8 и литерал строки с широким символом не могут быть конкатенированы.

(с C11)
(до C23)

Если два строковых литерала имеют разные префиксы кодировки, конкатенация является ошибочной.

(с C23)

Во-вторых, на стадии трансляции 7 к каждому строковому литералу добавляется нулевой терминатор, а затем каждый литерал инициализирует безымянный массив со статическим сроком хранения и размером, достаточным для хранения содержимого строкового литерала плюс один нулевой терминатор.

char* p = "\x12" "3"; // creates a static char[3] array holding {'\x12', '3', '\0'}
                      // sets p to point to the first element of the array

Строковые литералы не могут быть изменены (и, фактически, могут быть размещены в памяти только для чтения, например, .rodata). Если программа пытается изменить статический массив, образованный строковым литералом, поведение не определено.

char* p = "Hello";
p[1] = 'M'; // Undefined behavior
char a[] = "Hello";
a[1] = 'M'; // OK: a is not a string literal

Не требуется и не запрещено, чтобы идентичные строковые литералы ссылались на одно и то же место в памяти. Кроме того, перекрывающиеся строковые литералы или строковые литералы, которые являются подстроками других строковых литералов, могут быть объединены.

"def" == 3+"abcdef"; // may be 1 or 0, implementation-defined

Примечания

Строковый литерал не обязательно является строкой; если строковый литерал содержит вложенные нулевые символы, он представляет массив, который содержит более одной строки:

char* p = "abc\0def"; // strlen(p) == 3, but the array has size 8

Если действительный шестнадцатеричный символ следует за шестнадцатеричной escape-последовательностью в строковом литерале, это не скомпилируется в качестве недопустимой escape-последовательности, но конкатенация строк может использоваться в качестве обходного пути:

//char* p = "\xfff"; // error: hex escape sequence out of range
char* p = "\xff""f"; // okay, the literal is char[3] holding {'\xff', 'f', '\0'}

Строковые литералы могут использоваться для инициализации массивов, и если размер массива на единицу меньше размера строкового литерала, нулевой терминатор игнорируется:

char a1[] = "abc"; // a1 is char[4] holding {'a', 'b', 'c', '\0'}
char a2[4] = "abc"; // a2 is char[4] holding {'a', 'b', 'c', '\0'}
char a3[3] = "abc"; // a3 is char[3] holding {'a', 'b', 'c'}

Кодировка символьных строковых литералов (1) и литералов строк с широкими символами (5) определяется реализацией. Например, gcc выбирает их с помощью опций командной строки -fexec-charset и -fwide-exec-charset.

Хотя конкатенация смешанных литералов строк с широкими символами разрешена в C11, почти все компиляторы отклоняют такую конкатенацию (единственным известным исключением является SDCC), и опыт её использования неизвестен. В результате разрешение конкатенации смешанных литералов строк с широкими символами удалено в C23.

Пример

#include <inttypes.h>
#include <locale.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <uchar.h>
 
int main(void)
{
    char s1[] = "a猫🍌"; // or "a\u732B\U0001F34C"
#if __STDC_VERSION__ >= 202311L
    char8_t
#else
    char
#endif
    s2[] = u8"a猫🍌";
    char16_t s3[] = u"a猫🍌";
    char32_t s4[] = U"a猫🍌";
    wchar_t s5[] = L"a猫🍌";
 
    setlocale(LC_ALL, "en_US.utf8");
    printf("  \"%s\" is a char[%zu] holding     { ", s1, sizeof s1 / sizeof *s1);
    for(size_t n = 0; n < sizeof s1 / sizeof *s1; ++n)
        printf("0x%02X ", +(unsigned char)s1[n]);
    puts("}");
    printf(
#if __STDC_VERSION__ >= 202311L
    "u8\"%s\" is a char8_t[%zu] holding  { "
#else
    "u8\"%s\" is a char[%zu] holding     { "
#endif
, s2, sizeof s2 / sizeof *s2);
    for(size_t n = 0; n < sizeof s2 / sizeof *s2; ++n)
#if __STDC_VERSION__ >= 202311L
       printf("0x%02X ", s2[n]);
#else
       printf("0x%02X ", +(unsigned char)s2[n]);
#endif
    puts("}");
    printf(" u\"a猫🍌\" is a char16_t[%zu] holding { ", sizeof s3 / sizeof *s3);
    for(size_t n = 0; n < sizeof s3 / sizeof *s3; ++n)
       printf("0x%04" PRIXLEAST16" ", s3[n]);
    puts("}");
    printf(" U\"a猫🍌\" is a char32_t[%zu] holding { ", sizeof s4 / sizeof *s4);
    for(size_t n = 0; n < sizeof s4 / sizeof *s4; ++n)
       printf("0x%08" PRIXLEAST32" ", s4[n]);
    puts("}");
    printf(" L\"%ls\" is a wchar_t[%zu] holding  { ", s5, sizeof s5 / sizeof *s5);
    for(size_t n = 0; n < sizeof s5 / sizeof *s5; ++n)
       printf("0x%08X ", (unsigned)s5[n]);
    puts("}");
}

Возможный вывод:

  "a猫🍌" is a char[9] holding     { 0x61 0xE7 0x8C 0xAB 0xF0 0x9F 0x8D 0x8C 0x00 }
u8"a猫🍌" is a char[9] holding     { 0x61 0xE7 0x8C 0xAB 0xF0 0x9F 0x8D 0x8C 0x00 }
 u"a猫🍌" is a char16_t[5] holding { 0x0061 0x732B 0xD83C 0xDF4C 0x0000 }
 U"a猫🍌" is a char32_t[4] holding { 0x00000061 0x0000732B 0x0001F34C 0x00000000 }
 L"a猫🍌" is a wchar_t[4] holding  { 0x00000061 0x0000732B 0x0001F34C 0x00000000 }

Ссылки

  • Стандарт C23 (ISO/IEC 9899:2023):
    • 6.4.5 Литералы строк (стр. TBD)
  • Стандарт C17 (ISO/IEC 9899:2018):
    • 6.4.5 Литералы строк (стр. 50-52)
  • Стандарт C11 (ISO/IEC 9899:2011):
    • 6.4.5 Литералы строк (стр. 70-72)
  • Стандарт C99 (ISO/IEC 9899:1999):
    • 6.4.5 Литералы строк (стр. 62-63)
  • Стандарт C89/C90 (ISO/IEC 9899:1990):
    • 3.1.4 Литералы строк

См. также

Документация C++ для литерала строки

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/language/string_literal

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API