2009-09-27 1 views
11

Допустим, у нас есть массив символьных указателейМассив char * должен заканчиваться на ' 0' или " 0"?

char* array[] = { "abc", "def" }; 

Теперь то, что должно быть помещены в конце концов?

char* array[] = { "abc", "def", '\0' }; 

или

char* array[] = { "abc", "def", "\0" }; 

Хотя обе работы. У нас есть только поставить условие, чтобы проверить конец соответственно

как

array[ index ] != '\0'; 

или

array[ index ] != "\0"; 

Мой вопрос в том, какой из них является лучшим способом? Что используется большинством программистов?

Редактировать

Большинство ответов говорят, что NULL лучше, чем '\ 0' и "\ 0". Но я всегда думал, что

NULL является такой же, как «\ 0», который является такой же, как 0х0 или 0

это неправильно?

+1

Что касается редактирования, In C NULL является указателем (обычно определяется (void *) 0. '\ 0' является символьной константой, поэтому при использовании символьной константы, где ожидается указатель, и происходит неявное преобразование. происходит преобразование любого целочисленного нулевого результата в указатель NULL, но он не дает понять, что вы указали указатель. Лучше просто использовать литеральную константу integer zero IMO. Как это происходит на C++, это предпочтительный подход в любом case, но в C++ макрос NULL определяется так же (см. стандартные файлы заголовков вашего компилятора). – Clifford

ответ

24

Я бы положил его на NULL. Зачем? Потому что вы не можете сделать что-либо из них:

array[index] == '\0' 
array[index] == "\0" 

Первый из сравнения char * к char, который не то, что вы хотите. Вам нужно будет это сделать:

array[index][0] == '\0' 

Второй, даже не работает. Вы сравниваете char * с char *, да, но это сравнение бессмысленно. Он проходит, если два указателя указывают на одну и ту же часть памяти. Вы не можете использовать == для сравнения двух строк, вы должны использовать функцию strcmp(), потому что C не имеет встроенной поддержки строк за пределами нескольких синтаксических тонкостей (и я имею в виду несколько). Принимая во внимание, что:

array[index] == NULL 

Работает отлично и передает вашу точку.

+0

. На самом деле сравнение 'char *', вероятно, работало для OP, поскольку компилятор объединил два идентичных строковых литерала. Я согласен, что сравнение в принципе бессмысленно. –

+0

Я знаю, что это, вероятно, сработало, но отнюдь не гарантировано работать, и на него никогда нельзя полагаться, и поэтому бессмысленно. Если он работает, он работает, потому что у вас есть умный компилятор, или потому, что вам повезло. –

+1

Является ли NULL не таким же, как '\ 0'? Я понимаю, что NULL == '\ 0' == 0x0. Есть неверные данные. –

0

Ну, технически '\0' является символом, в то время как "\0" является строкой, поэтому, если вы проверяете символ нулевого окончания, первое верно. Однако, как Chris Lutz points out in his answer, ваше сравнение не будет работать в текущей форме.

+0

Использование '' \ 0'' сравнивает символ 'char *' с 'char', который похож на сравнение яблок для апельсинов. На самом деле это не так. –

+1

@Chris: с использованием '' \ 0'' сравнивает символ 'char *' с 'int' Christoph

+0

@ Christoph - вот что такое Крис Лу tz указал.Вместо того, чтобы обновлять мой ответ, я указал свой ответ на его – ChrisF

5

Из этих двух символов первая ошибка типа: '\ 0' является символом, а не указателем. Компилятор все еще принимает его, потому что он может преобразовать его в указатель.

Второй «работает» только по совпадению. «\ 0» - строковый литерал из двух символов. Если они встречаются в нескольких местах исходного файла, компилятор может, но не обязательно, сделать их идентичными.

Таким образом, правильный способ, чтобы написать первый является

char* array[] = { "abc", "def", NULL }; 

и вы проверить array[index]==NULL. Правильный способ проверки для второго - array[index][0]=='\0'; вы также можете отбросить «\ 0» в строке (т. е. запишите его как ""), так как это уже будет содержать нулевой байт.

+0

Мне интересно, что эта проблема имеет два ответа, которые работают, но ни одна из них не является технически правильной и не работает по той причине, что OP думает, что они делают. –

0

Прекращение массива символов с нулевым символом - это просто соглашение, специально предназначенное для строк в C. Вы имеете дело с чем-то совершенно другим - массивом указателей на символы, поэтому он действительно не имеет отношения к соглашение для строк C. Конечно, вы можете выбрать его с помощью нулевого указателя; возможно, это может быть ваша конвенция для массивов указателей. Есть и другие способы сделать это. Вы не можете спросить людей, как это «должно» работать, потому что вы принимаете какое-то соглашение, которого нет.

+0

Соглашение существует для массивов переменной длины: используйте NULL в качестве значения дозорного устройства. – u0b34a0f6ae

6

В соответствии со спецификацией C99,

  • NULL расширяется до нулевого указателя постоянной, которая не требуется, чтобы быть, но обычно имеет тип void *
  • '\0' постоянный характер; символьные константы имеют тип int, поэтому он equivalen в обычный 0
  • "\0" является завершающим нулем строка символов и приравненных к соединению буквального (char [2]){ 0, 0 }

NULL, '\0' и 0 все нулевые постоянные указатели, так что они все выводят нулевые указатели при конверсии, тогда как "\0" дает ненулевой номер char * (который должен рассматриваться как const, так как модификация не определена); поскольку этот указатель может быть различным для каждого вхождения литерала, он не может использоваться в качестве контрольного значения.

Хотя вы можете использовать любое целое постоянное выражение стоимости 0 как нулевая константу указателя (например, '\0' или sizeof foo - sizeof foo + (int)0.0), вы должны использовать NULL, чтобы сделать ваши намерения ясны.

+0

Несмотря на то, что «NULL» расшифровывается до нулевого указателя только в том случае, если он определен как «(void *) 0' (в этом случае это и то, и константа нулевого указателя) :) Если это произойдет чтобы быть '0' или схожим, то это только константа нулевого указателя, которая еще должна быть преобразована в нулевой указатель :) –

+0

@litb: на самом деле' '\ 0'' не может быть действительной константой нулевого указателя, так как это постоянная символа (C99 6.4.4.4), а не целочисленная константа (C99 6.4.4.1); символьные константы иногда называют целыми символьными константами, но делает ли это «целочисленным постоянным выражением», как того требует C99 6.3.2.3? – Christoph

+0

@Christop 6.6/6 :) –

-1

Нулевое окончание - плохой дизайн, который лучше всего оставить в книгах по истории. За c-струнами по-прежнему много инерции, поэтому туда нельзя избежать. Но нет смысла использовать его в примере OP.

Не используйте терминатор и используйте sizeof (array)/sizeof (array [0]), чтобы получить количество элементов.

+1

+1 для sizeof array/sizeof array [0]. Но вы думаете, что это хорошая причина для того, чтобы не использовать терминатор? –

+1

это работает только в том случае, если массив объявлен в области - если он передан указателем, то вы не можете делать 'sizeof (array)', и вы можете получить длину только путем передачи размера через параметр или поиска нулевого терминатора , –

+0

Я должен был быть более ясным. Передайте количество элементов вокруг вашего массива. Безопаснее и понятнее, чем использование терминатора. – Alan