2016-08-13 2 views
-2

У меня есть вопрос для лучшего understing, как массивы и nullbytes работают в С.C массивы и нулевой байт

Допустим, у меня есть целочисленный массив из 13 ячеек. Предположим, я хочу, чтобы номера ячеек: 1, 2, 3 и 10 имели значение. Остальные, оставшиеся по умолчанию, автоматически получают значение nullchar \ 0 как значение?

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

Я написал простую прогу для проверки того, что и кажется, что это так:

int nums[13] = {1,2,3}; 
nums[10] = 69; 
int i; 
for(i=0;i<13;i++) { 
    if(nums[i]=='\0') { 
     printf("null char found! in position: %d\n",i); 
    } 
    else { 
     printf("element: %d found in position: %d of int array\n",nums[i],i); 
    } 
} 

return 0; 

здесь выход:

элемент: 1 находится в положении: 0 ИНТ массив

элемент: 2 найдено в позиции: 1 из массива Int

элемент: 3 находится в положении: 2 Int массива

null char найден! в положении: 3

null char найденный! в положении: 4

null char найденный! в положении: 5

null null найденный! в позиции: 6

null char найденный! в положении: 7

null char найден! в положении: 8

null char найденный! в положении: 9

элемент: 69 находится в положении: 10 ИНТ массива

нулевой символ найден! в положении: 11

null char найденный! в положении: 12

| 1 | | 2 | | 3 | | \ 0 | | \ 0 | | \ 0 | | \ 0 | | \ 0 | | \ 0 | | 69 | | \ 0 | | \ 0 | | \ 0 |

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

Должен ли нулевой символ быть только один раз в конце всего массива? Благодаря

+0

Статически выделенная память заполняется 0 для скаляров или NULL (\ 0) для указателей. Если вы нажмете \ 0 в качестве скаляра, он будет преобразован в 0. Нет такой вещи, как «пустой». Вы не должны сравнивать NULL (\ 0) с int в любом случае, используйте литерал 0. – Tibrogargan

+4

«Мое понимание \ 0 состояло в том, что нулевой байт всегда находится в конце массива ..» совершенно неверно. Вы путаете регулярные массивы и строки C. – usr2564301

+0

@Tibrogargan '\ 0' (символ NUL) не совпадает с указателем' NULL'. '\ 0' - это байт со всеми битами, установленными в 0, которые всегда будут сравниваться с' int' 0. – Kninnug

ответ

3

Там не требуется в С, массивов нужно \0 в конце. NUL-терминатор нужен только для C строк (которые обычно имеют char или wchar_t или другие символы ). В строке C байт \0 также не должен находиться в конце массива, который содержит его, но он должен быть в конце строки. Вполне допустимо иметь 0 в любом месте массива. Но если этот массив используется как строка, то стандартные функции строки C будут интерпретировать значение 0 с наименьшим индексом, чтобы обозначить конец строки.

При объявлении переменного (nums) в C с инициализатором ({1,2,3}) в

int nums[13] = {1,2,3}; 

всех индексы, которые не упомянуты в инициализаторах (3 по 12) имеют их значение инициализируется 0. Невозможно иметь «пустые» ячейки в массиве. Все ячейки будут иметь значение, это зависит от программы (mer), какие значения считаются пустыми.

1

Типы C соответствуют памяти, а в памяти нет реальной концепции «пустой». Существуют языки, где все (или почти) можно сделать «пустым», помещая некоторую «пустую» константу (например, у Python есть None), но C этого не допускает. Одна из причин не допускать этого заключается в том, что он заставляет вас иметь специальный универсальный шаблон для пустого состояния, и это имеет низкое влияние. Например, символ может принимать любое значение от 0 до 255 включительно. Это потому, что символы занимают 8 бит. Если вы также хотели иметь пустое состояние, не жертвуя возможными значениями для символов, вам понадобится хотя бы еще один бит, поскольку 8 других битов могут использоваться по законным причинам, и это нежелательно по многим причинам.

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

char foo[4] = {1, 2, 3, 4}; 

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

char foo[4] = {1, 2}; 

элементы 0 и 1 имеют определенное значение, но 2 и 3 нет, и с этим синтаксисом C предположим, что вы хотите, чтобы сделать их ноль. С другой стороны, если вы пишете:

char foo[4]; 

вы не назначая никакого значения к любому элементу, и в этом случае C не будет инициализировать массив на всех. Это будет неопределенное поведение, чтобы читать из него; на практике, как правило, элементы будут принимать значения того, что раньше существовало в своем местоположении памяти.

-1

Прежде всего, вы вводите в заблуждение строки C с регулярными массивами. Со строками всегда есть \0 в конце массива char. Это означает конец строки. Например, говорят, что у вас есть это:

char myText[] = "hello"; 

В этом случае место массива выглядит следующим образом:

 

    myText[0] = 'h'; 
    myText[1] = 'e'; 
    myText[2] = 'l'; 
    myText[3] = 'l'; 
    myText[4] = 'o'; 
    myText[5] = '\0'; 

Однако массивы не заканчивается с '\0'. Возьмем другой пример:

int myArray[3] = {1, 2, 3}; 

В соответствии с вашим правилом, так как массивы должны заканчиваться '\0', это не юридическое заявление, так как мы только дать массиву 3 элемента вместо 4, и мы должны были бы 4 элементы включают '\0'. Однако это вполне юридический оператор в C. Очевидно, что пространство для '\0' не требуется в массивах, только в конце строк C.

Также отметим, что '\0' эквивалентно целому, а Kninnug отметил в комментариях:

\0 (нулевой символ) не совпадает с NULL-указателя. \0 является байт со всеми битами, установленными в 0, который всегда будет сравнить равен INT 0.

Итак, в вашей программе, вы можете просто одинаково проверить, если:

if(nums[i] == 0) 

Теперь, давайте докажите, почему вы получаете свою продукцию.

Должен ли нулевой символ быть только один раз в конце всего массива?

Нет. Остальные элементы, оставшиеся пустыми, будут инициализированы нулевым значением. Вот почему вы видите результат, который у вас есть; элементы, которые не являются num[0], num[1], num[2], или num[10], будут инициализированы нулем. Так как вы проверяете для \0 (также 0), то все остальное с не теми элементами будет 0.


alk Как отмечено в комментариях, нулевой символ и нулевой указатель буквальным различны. В конце строк C вы видите нулевой символ (NUL), который равен '/0' или 0. Однако литерал нулевого указателя (NULL) отличается.

+0

Может ли кто-нибудь объяснить пониженное голосование, чтобы я мог улучшить сообщение? – iRove

+0

NUL (имя для нулевого символа) и 'NULL' (литерал нулевого указателя) - это разные виды животных. – alk

+0

C-"string" - это массив символов, по крайней мере, один из его элементов, равный NUL, нулевой символ (равный '' \ 0'', который равен '0'). Массив символов не обязательно является C- "строкой". – alk

0

NULL определяется как (недействительными *) 0 - Он равен нулю с общей отливке PTR, которым равно персонажа NUL (в \ 0) код ASCII - 0

Массивы не должны заканчиваться любой специальный знак/число.

струны действительно должны закончить с особым характером, и причина проста, она позволяет функции Wich работает на струнах «знать», где строка заканчивается, например:

char str[100] = {'h','e','l','l','o',0}; // same as {'h','e','l','l','o','\0'} 
printf("%s",str); 

печатает: привет

Если последний символ в строке не был NUL, он будет печатать 95 символов мусора после строки («привет»), потому что размер массива равен 100, и компилятор не знает, где заканчивается строка.

Несмотря на то, что нуль в 6-й ячейке заканчивает строку в большинстве компиляторов, вы можете установить только строку «hello», и они будут заполнять остальную ячейку нулями, поэтому в обоих случаях это будет нормально.

+0

NUL (имя для нулевого символа) и 'NULL' (литерал нулевого указателя) - это разные виды животных. – alk

+0

Я не писал, что они одно и то же. –