В следующем коде поведение не определено?Невозможно понять результат этого фрагмента C
#include<stdio.h>
int main()
{
printf(7+"%c","sundaram");
}
Его печать «арам». Не могу понять, как это сделать.
В следующем коде поведение не определено?Невозможно понять результат этого фрагмента C
#include<stdio.h>
int main()
{
printf(7+"%c","sundaram");
}
Его печать «арам». Не могу понять, как это сделать.
Как было указано другими, поведение не определено, поскольку выражение 7+"%c"
не указывает на элемент внутри массива или один за концом массива. См. Стандарт онлайн-языка C, проект n1256, § 6.5.6 для деталей.
По совпадению ваши строки раскладывают в памяти, как это (используя воображаемую начальный адрес):
Address 0x00 0x01 0x02 0x03
------- ----------------------
0x00008000 '%' 'c' 0 's'
0x00008004 'u' 'n' 'd' 'a'
0x00008008 'r' 'a' 'm' 0
«% С» начинается с 0x00008000 и «сундарам» начинается в 0x000080003.
При вызове
printf(7+"%c", "sundaram");
выражение массив «% С» преобразуется из типа char [3]
к char *
, и его значение является адресом первого элемента в массиве, или 0x00008000. Таким образом, выражение 7+"%c"
оценивает значение 7 + 0x00008000 или 0x00008007. Строка, начинающаяся с 0x00008007, - «aram».
Поскольку «aram» не содержит спецификаторов преобразования, второй аргумент («sundaram», который оценивается как 0x00008003) оценивается, но в противном случае игнорируется (§ 7.19.6.1, ¶ 2).
Поскольку поведение не определено, любой результат возможен; этот конкретный результат не гарантированно произойдет с другим компилятором или с разными настройками компилятора.
Это неопределенное поведение.
Строковый литерал в C является указателем на блок предварительно инициализированной памяти.
По совпадению, ваши два строковых литерала занимают смежные блоки памяти.
Когда вы добавляете 7
к указателю на первый литерал, вы в конечном итоге указываете на середину следующего литерала. Данные
вашей программы расположена в памяти, как это:
%c\0sundaram\0 | | "%c" --^ | 7 + "%c" ------^
Таким образом, вы в конечном итоге вызова printf
с двумя указателями в ту же строку ("adam", "sundadam")
и без спецификаторов формата.
Поведение не определено. Так получилось, что данные хранятся в памяти следующим образом: «% c \ 0sundaram \ 0», и вы получаете часть строки «sundaram» в качестве аргумента строки форматирования (при отсутствии спецификаторов формата в оставшейся строке формата аргументы printf игнорируются).
Спасибо.Вы сказали «в отсутствие спецификаторов формата .....» Но есть спецификатор формата. Нет? – Daud
Спецификатора формата для printf не существует. Эффект неопределенного поведения в вашем случае передает «aram» для printf как строку формата, которая не имеет спецификаторов формата. – zeuxcg
Еще раз спасибо. я понял – Daud
Спасибо. Но почему он не рассматривает «% c» как спецификатор формата? если мы заменим 7 на 0, он выдает предупреждение, и на выходе ничего не отображается, когда он должен показывать «% c» – Daud
Потому что, когда он смотрит на последовательные символы в памяти, начиная с 7, где «% c», он никогда видит «% c». –
@Duad: Вы передаете ему указатель на '' adam '', а не ''% c ". – SLaks