Ваша программа вызывает неопределенное поведение, поэтому на самом деле нет никаких ограничений на то, что она может выводить.
char ***x = "jjhljlhjlhjl";
Хотя x
является указателем на указатель на указатель, ему присваивается адрес строкового литерала.
char **q = *x;
q
является указателем на указатель, и присваивается результат разыменования x
. Так как x
на самом деле указывает на объект несовместимого типа, результат его переноса не определен.
Если мы делаем вид, как это должно работать, то *x
теперь указатель на указатель, и поэтому оно может относиться к sizeof(char **)
байт строкового литерала, как если бы это был адрес и присвоить это значение q
.
printf("x:%s\n",x);
Поскольку x
является указателем, что значение указателя передается printf()
. Поскольку предоставляется %s
, значение указателя обрабатывается как строка. Поскольку x
был назначен адрес строкового литерала, эта строка печатается.
printf("q:%s\n",&q);
Адрес q
передается printf()
. Поскольку предоставляется %s
, значение указателя обрабатывается как строка. Однако переупорядочение содержимого этого указателя фактически является sizeof(char **)
байтами строкового литерала. Нет гарантии, что прочитанные байты будут правильно завершены NUL
, так что просто случайно что-то напечатано вообще.
Это 'int main()', btw. – alk
На самом деле, K & R C допускает объявления функций без типов (подразумевается «int») –