Простой вопрос об объявлении пустой строки в C - PullRequest
1 голос
/ 09 января 2020

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

static uint8_t test[3] = {'0','0','0'};   // (1)
static uint8_t test[3] = "";              // (2)
uint8_t test[3] = "";                     // (3)

В чем разница между (2) и (3). Это нормально или плохая практика программирования?

Кроме того, как строка хранится в памяти?

Есть ли вероятность, что мы напишем за пределами размера 3?

Когда я делаю:

uint8_t test[3] = ""; // 



test[0] = 0  test[1] = 0  test[2] = 0  test[3] = /0 (null character indicating the end of the string)

или делаю

uint8_t test[3] = "123";



test[0] = ‘1’ 
test[1] = ‘2’ 
test[2] = ‘3’ 
test[3] = /0 (null character indicating the end of the string)

Где хранится нулевой терминатор?

И в чем разница между

test[3] = ""
test[3] = '\0'

Мне кажется, что я обнуляю все позиции, но также обнуляю от позиции 3 в качестве начального адреса, и поэтому я запутался.

и

uint8_t test[3] = ""
uint8_t test[3] = '\0'

1 Ответ

3 голосов
/ 09 января 2020

Я не получил никакого предупреждения компилятора при объявлении строки следующими способами

Вы не должны этого делать, поскольку весьма вероятно, что uint8_t соответствует unsigned char.

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

В чем разница между (2) и (3)

Возможно, продолжительность соединения и хранения. Зависит от того, где переменные объявлены. Это не имеет ничего общего с uint8_t или строками как таковыми.

Это нормально или плохая практика программирования?

Можно использовать uint8_t для строк, но немного странно в случае программирования generi c C.

Существуют особые случаи, такие как определенные виды встроенных систем, которые хотят гарантировать, что символы всегда имеют тип без знака, потому что они генерируют таблицы отображаемых символов или строковые протоколы и т. Д. c. В таких системах всегда следует использовать uint8_t или unsigned char и никогда char.

Кроме того, как строка хранится в памяти?

Как 3 байты, инициализированные нулевым значением (0x00). Не путать с символом ноль '0' (0x30).

Где сохраняется снова, зависит от области, в которой он объявлен. Обратите внимание, что хранится сам строковый литерал в другой памяти, чем массив чтения / записи. Промышленный стандарт де-факто - это что-то вроде этого примера .

Есть ли вероятность, что мы напишем за пределами размера 3?

Да, если вы делаете глупости вроде test[3] = '\0';. Массив, объявленный с размером 3, может обращаться только к элементам 0, 1 и 2, поскольку индексирование массива индексируется нулями в C.

test [3] = '\ 0' ... Где хранится ли нулевой терминатор?

Никто не знает, это неопределенное поведение. Это не гарантированно хранится где-либо, и ваша программа может взломать sh. Или вам не повезло, и ваша система позволяет вам писать в эту область памяти.

В чем разница между test[3] = "" и test[3] = '\0'

Первый является синтаксической ошибкой, последняя записывает за пределы массива. Ни один из них не является правильным.

, поэтому я запутался

Вы не понимаете, как декларировать массив по сравнению с доступом к массиву. Они выглядят одинаково, но делают разные вещи. uint8_t test[3] = ""; может использоваться только во время объявления / инициализации. [3] во время объявления означает массив размера 3. Но [3] во время доступа к массиву означает доступ к элементу 3 в массиве с нулевым индексом, который имеет только элементы [0], [1] и [2].

Инициализатор "" эквивалентен {'\0'}, нулевое завершение. Кроме того, в C есть правило, гласящее, что если массив частично инициализирован, все элементы, которые не были явно инициализированы, будут неявно инициализированы равными нулю. В случае "" первый элемент явно инициализируется нулем, потому что это нулевой терминатор, а остальные неявно равны нулю, потому что так работают массивы.

...