Это ужасная работа; кто бы ни написал его, его следует вынести за заднюю часть сарая и избивать до тех пор, пока он не пообещает больше никогда не писать такой код за пределами записи для IOCCC (Международного конкурса кодов с запутанным кодом C).
Правая часть выражения
*--ptr = "0123456789abcdef"[num%base];
использует тот факт, что строковый литерал преобразуется в указатель. Если вы видели:
const char digit[] = "0123456789ABCDEF";
*--ptr = digit[num%base];
вы бы не волновались. Выражение со строковым литералом эквивалентно этому. (По крайней мере, они имели благодать не писать:
*--ptr = (num % base)["0123456789ABCDEF"];
Это также эквивалентно в силу соотношения:
a[i] <==> i[a] <==> *(a + i) <==> *(i + a)
где двуглавые стрелки указывают на эквивалентность.
Использование *--ptr
извлекает цифры назад, от наименее до наиболее значимого. Это работает, потому что указатель инициализируется до конца статического буфера (и очень важно, чтобы он был статическим, поскольку возвращаемое значение функции - указатель на этот буфер).
Однако код не очень полезен, потому что вы не можете сохранить значение из вызова и распечатать его позже, если был другой вызов. Вы не могли написать:
printf("%s = %s = %sn", convert(65,8), convert(65,10), convert(65,16));
Или, точнее, вы можете, но вы увидите одно и то же значение трижды один из «101», «164» или «140» в первой позиции, а также «01» или «64» или «40» для двух других позиций, и в стандарте C не указано, какие значения вы увидите. Статический буфер также предотвращает поточно-ориентированный код.
В общем, это странный код для показа новичкам. Это работает, но это все, что можно сказать об этом. Он также не проверяет свою базу на достоверность, поэтому convert(65, 18)
может привести к неопределенному поведению. (База 17 в худшем случае будет ссылаться на '\0'
, который не был предназначен, что приводит к путанице.)