2015-08-11 4 views
3
#include<stdio.h> 

void main() 
{ 
    char a[10][5] = {"hi", "hello", "fellow"}; 
    printf("%s",a[0]); 
} 

Почему этот код печати толькопривет2-D массив символов

#include<stdio.h> 

void main() 
{ 
    char a[10][5] = {"hi", "hello", "fellow"}; 
    printf("%s",a[1]); 
} 

Хотя этот код печатает "hellofellow"

ответ

2

Почему этот код только печать привет

Вы сказали printf напечатать строку, хранящуюся в a[0], и эта строка случается "hi".

Хотя этот код печатает «hellofellow»

Это один случайно, ведь ваш код должен быть отвергнут компилятором из-за a constraint violation:

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

Строка "fellow", в частности, 'w' в конце этого не вписывается в char[5] инициализируется, и это нарушает стандарт C. Возможно, также случайно, ваш компилятор обеспечивает расширение (что делает его технически не-C компилятор), и поэтому вы не видите the error messages, что я делаю:

prog.c:3:6: error: return type of 'main' is not 'int' [-Werror=main] 
void main() 
    ^
prog.c: In function 'main': 
prog.c:5:37: error: initializer-string for array of chars is too long [-Werror] 
    char a[10][5] = {"hi", "hello", "fellow"}; 
            ^

Обратите внимание, что второе сообщение об ошибке жалуется "fellow" , но не "hello". Ваша "hello" инициализация is valid by exception:

Массив типа символов может быть инициализирован с помощью строки символов буквальной или UTF-8 строки буквальной, необязательно заключена в скобках. Последовательные байты строкового литерала (, включая завершающий нулевой символ, если есть номер или массив неизвестного размера) инициализируют элементы массива.

Акцент мой. То, что подчеркивается в разделе разделов, состоит в том, что если не хватает места для терминала '\0' символа, который не будет использоваться в инициализации.

2

Ваш код:

char a[10][5] = {"hi", "hello", "fellow"}; 

Распределяет 10 char [5]

«привет» занимает 5, так что нет места для завершающего \0, поэтому он работает в «парень»

Если вы попробуете это, a [3] должно быть «ш», потому что «собрата "слишком большой и„ж“пробегает от a[2] до a[3]

Помимо того, что непредсказуемое поведение, это сбивает с толку то, что вы пытаетесь сделать

1

Это недеформированной оштрафованное поведение из-за недостаточного места для хранения \0 персонажа.

Обратите внимание: выделенная память содержит 5 байт в строке в вашем массиве строк. Таким образом, для a[1] недостаточно памяти для хранения символа \0, поскольку все пять байтов назначаются "hello".

Таким образом, последующая память считывается до тех пор, пока не будет найден символ \0.

Таким образом, вы можете изменить строку:

char a[10][5] = {"hi", "hello", "fellow"}; 

к

char a[][7] = {"hi", "hello", "fellow"}; 

Почему этот код печати только привет

Это происходит потому, что \0 символ уже встречается на a[0][2], и поэтому чтение символов прекращается.

+0

["Последовательные байты строкового литерала (включая завершающий нулевой символ **, если есть комната ** или массив неизвестного размера) инициализируют элементы массива."] (Http: // www. iso-9899.info/n1570.html#6.7.9p14), акцент мой. Это не '' \ 0'', вызывающий UB. – Sebivor

2

Будет выдано stringnull-terminated.

И элемент hello имеет длину 5. Объявите свой массив как a[10][7], тогда вы получите намеченный вывод.

Смотрите здесь - https://ideone.com/c2zUs0

Почему этот код только печать привет

Поскольку a[0][2] является null, указывающий окончание, таким образом, давая вам hi.

1

Что делает ваш код:

Посмотрите на следующее заявление:

char a[10][5] = {"hi", "hello", "fellow"}; 

Он выделяет 10 строки. 5 символов выделяются для каждого индекса a.

Что такое проблема:

Строки Null Terminated всегда есть null-terminator необходимо хранить для заданных символов, за исключением, поэтому в основном используется размер массива numOfCharacters+1, дополнительный один байт для нулевой терминатор. Когда вы инициализируете массив с точно size количеством символов, то null terminator пропускается. Обычно значение массива символов печатается до тех пор, пока первый \0 (нулевой ограничитель) не будет найден. Также обратите внимание на this.

Решение:

Нет необходимости беспокоиться об этой проблеме, все, что вам нужно сделать, это просто установить размер, равный numOfCharactersInString + 1. Вы можете использовать следующее заявление:

char a[10][7] = {"hi", "hello", "fellow"}; 

Поскольку самая большая строка "fellow" которая содержит 6 символы, необходимо установить размер 6 + 1, именно поэтому оператор должен использовать char a[10][7] вместо полукокса a[10][5]

Надежда это помогает.

1

При объявлении массива символов в 2-D как

char a[10][5] = {"hi", "hello", "fellow"}; 

полукокса а [10] [5] оставляет память для хранения 10 строк каждый длиной 5, что означает 4 символа + 1 '\ 0' , Следует отметить, что элементы массива хранятся в смежных ячейках памяти.

a [0] указывает на первую строку, [1] на вторую и так далее.

Также при инициализации массива частично другие неинициализированные элементы становятся 0 вместо значений мусора.

Теперь в вашем случае, после инициализации, если вы пытаетесь визуализировать массив было бы что-то вроде

привет \ 0 \ 0 \ 0hellofello \ 0 \ 0 ...

Теперь команды

printf("%s",a[0]); 

печатает символы, начинающиеся с «h» «привет», и прекращает печать, когда встречается «\ 0», поэтому печатается «привет».

Теперь для второго случая,

printf("%s",a[1]); 

символы печатаются, начиная с «Н» «привет» до а «\ 0» является encountered.Now символ «\ 0» символ встречается только после того, как печать «hellofello» и, следовательно, выход.

+0

Я не вижу никакого «нулевого символа» после «hellofello». После этого 'w' не существует« нулевой символ ». – ameyCU

+0

«парень» усечен до «fello», так как может храниться не более пяти символов. Символ рядом с «fello» равен «\ 0», так как он еще не инициализирован никаким другим значением. –

+0

Без нулевого завершения, которое будет неопределенным поведением. Это дает UB и ничего, кроме этого ничего. – ameyCU

Смежные вопросы