Интересно, почему

#c #printf #character #c-strings #conversion-specifier

Вопрос:

 #include <stdio.h>

int main(void)
{

    char var = 'z';

    printf("[buf]: %s n", amp;var); // the output is z~~~~~, but the first char of output is only z. why??
}
 

Комментарии:

1. %s это для строк, так как же это все равно напечатает адрес? Кроме того, это неопределенное поведение. После этого не будет НУЛЕВОГО терминатора z .

Ответ №1:

Спецификатор преобразования s предназначен для вывода строк (или их частей): последовательностей символов, заканчивающихся нулевым символом '' .

Для вывода адреса объекта существует спецификатор преобразования p .

Вот демонстрационная программа.

 #include <stdio.h>

int main(void) 
{
    char s[] = "Hello";
    
    printf( "%sn", s );
    printf( "%pn", ( void * )s );
    
    return 0;
}
 

Вывод программы может выглядеть следующим образом

 Hello
0x7ffc86fe4372
 

Что касается кода в вашем вопросе, то он имеет неопределенное поведение, потому что выражение amp;var не указывает на строку, потому что переменная var определена следующим образом

 char var = 'z';
 

Если вы хотите вывести его адрес, то вы можете сделать это следующим образом

 printf("[buf]: %p n", ( void * )amp;var);
 

Ответ №2:

%s указывает printf принять указатель на первый символ строки и распечатать эту строку, вплоть до нулевого символа, указывающего на ее конец. Поскольку вы передаете адрес одного символа, printf печатает его и продолжает искать в памяти дополнительные символы для печати, пока не найдет байт, содержащий ноль. Поскольку %s , когда вы передаете указатель на один символ, а не на массив символов, заканчивающийся нулевым символом, поведение не определяется стандартом C.

Чтобы напечатать адрес, используйте %p и преобразуйте указатель в void * :

 printf("%pn", (void *) amp;var);