Пример источника
#include <stdio.h>
int main( void ) {
char tab[2][3] = {'1', '2', '\0', '3', '4', '\0'};
printf("%s\n", tab);
return 0;
}
Предупреждение о компиляции
$ gcc test.c
test.c: In function ‘main’:
test.c:5: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char (*)[3]’
Указатели - это указатели
Аргумент %s
для printf
указывает функции, что она будет получать указатель (на строку). Строка в C - это просто серия байтов, оканчивающаяся ASCII-Z. Переменная tab[2][3]
является указателем. Некоторые компиляторы выдают предупреждение о несоответствии указателя. Тем не менее, код должен по-прежнему печатать 12
, потому что код printf
пересекает память, начиная с указанного ему указателя (печатая символы по ходу), пока не найдет нулевой байт. 1, 2 и \ 0 непрерывно устанавливаются в памяти, начиная с адреса, представленного переменной tab
.
Эксперимент
В качестве эксперимента, что происходит, когда вы компилируете и запускаете следующий код:
#include <stdio.h>
int main( void ) {
char tab[2][3] = {'1', '2', '\0', '3', '4', '\0'};
printf("%s\n", tab[1]);
return 0;
}
Не бойтесь экспериментировать. Посмотрите, сможете ли вы придумать ответ, основываясь на том, что вы теперь знаете. Как бы вы указали tab
сейчас (в свете эксперимента), чтобы избавиться от предупреждения и по-прежнему отображать 12
?