Массивы символов с нулем в конце - PullRequest
0 голосов
/ 20 июня 2019

1.К какому из следующих символов добавлен нулевой символ-терминатор?

int main()
{
        char arr[]="sample";
        char arr2[6]="sample";
        char arr3[7]="sample";
        char* strarr="sample";  
        char* strarr1=arr;  
        char* strarr2=arr2; 
        char* strarr3=arr3; 

        return 0;
}

2.Сбой printf("%s",somestr) в случае:

  • somestr - это массив символов без нулевого символа завершения в конце?
  • somestr - это char*указывая на непрерывное расположение символов без нулевого символа завершения в конце?

Редактировать : Есть ли способ проверить в gdb char* или char массив завершен нулем или нет?

Ответы [ 2 ]

0 голосов
/ 20 июня 2019

Во-первых, "sample" называется строковым литералом. Он объявляет массив const char, заканчивающийся нулевым символом.

Давайте продолжим:

    char arr[]="sample";

Правая часть в массиве const char размера 7 (6 символов и '\0'. Размерность arr выводится из его инициализации и также равна 7. Массив char затем инициализируется из буквенной строки.

    char arr2[6]="sample";

arr2 имеет объявленный размер 6. Он инициализируется из строкового литерала размера 7: только объявленная позиция 6 инициализируется в {'s', 'a', 'm', 'p', 'l', 'e'} без завершающего нуля . Здесь все в порядке, за исключением того, что передача arr2 в функцию, которая ожидает завершенную нулем строку, вызывает неопределенное поведение.

    char arr3[7]="sample";

Объявленный размер и размер литеральной строки инициализации равны 7: это просто явная версия первого варианта использования. Довольно опасно, потому что если вы позже добавите один символ в строку инициализации, вы получите массив символов с ненулевым символом в конце.

    char* strarr="sample";  

Избегайте этого . Вы объявляете неконстантный указатель на строковый литерал. В то время как стандарт объявляет явно:

Если программа пытается изменить такой массив, поведение не определено.

strarr[3] = 'i' будет затем вызывать неопределенное поведение без предупреждения. При этом, при условии, что вы никогда не изменяете строку, у вас есть хорошая завершенная нулем строка.

    char* strarr1=arr;

Хорошо, вы объявляете указатель на другую строку. Или, точнее, указатель на первый символ другой строки. И это правильно завершается нулем.

    char* strarr2=arr2; 

У вас есть указатель на первый символ массива символов с ненулевым символом в конце ... Вы не можете передать arr2 функции, ожидающей массив символов с нулевым символом в конце, и вы не можете либо передать strarr2.

    char* strarr3=arr3;

У вас есть другой указатель, указывающий на строку. То же поведение, что и strarr1.


Согласно как проверить в GDB завершающий ноль , вы не можете напечатать его напрямую, потому что GDB знает достаточно строк C, чтобы автоматически прекратить печатать строку с первым нулевым символом. Но вы всегда можете использовать p arr[7], чтобы увидеть, является ли символ после массива нулевым или нет.

Для arr2, arr2+7 - один за массивом. Так что не определено, что там и в действительно плохой системе, использование p arr[7] может вызвать сигнал, потому что это может быть после конца сегмента памяти - но я должен признать, что я никогда не видел этого ...

0 голосов
/ 20 июня 2019

Каждый из arr и arr3 содержит строку с нулевым окончанием, выделенную в стеке при вызове функции.

strarr указывает на строку с нулевым символом в конце, выделенную в разделе данных только для чтения программы.

strarr1 указывает на строку с нулевым символом в конце, выделенную в стеке при вызове функции.

strarr3 указывает на строку с нулевым окончанием, выделенную в стеке при вызове функции.

str указывает на ту же строку, что и strarr1.

...