Код, который вызывает неопределенное поведение, может что-то сделать - вот почему это undefined.
Тем не менее, можно было бы сделать хороший догадываться, почему это происходит, чтобы сделать эту конкретную вещь на вашей машине используя ваш конкретный компилятор с точно параметры, которые вы использовали и скомпилирован на же будний день года с 6, вы понимаете, верно? Это undefined, и есть никаких объяснений, на которые можно положиться, даже если вы считаете, что знаете все переменные. Однажды, влажность падает, или что-то, и ваша программа может решить сделать что-то другое. Даже без перекомпиляции. Даже в двух итерациях того же цикла. Это просто неопределенное поведение.
В любом случае, аргументы с плавающей запятой в вашей платформе, вероятно, передаются в выделенные регистры с плавающей запятой (или выделенный стек с плавающей точкой), а не в основной стек. printf ("% g") ожидает аргумент с плавающей запятой, поэтому он выглядит в регистре с плавающей запятой. Но вы ничего не передавали в регистре с плавающей запятой; все, что вы передали, были двумя аргументами указателя, которые оба поместили в стек (или где бы ни были аргументы указателя, это также выходит за рамки стандарта C). Таким образом, второй вызов printf получает всякий мусор в этом конкретном регистре с плавающей запятой в последний раз, когда он был загружен. Так получилось, что последнее, что вы загрузили в этот регистр, было значением *p1
, в последнем вызове printf, чтобы значение снова использовалось.
Правила, определяющие (среди прочего), где аргументы функции размещены, поэтому функция знает, где их искать, в совокупности называется соглашением . Вероятно, вы используете x86 или производную, поэтому можете найти интересующую вас Wikipedia page on x86 calling conventions. Но если вы хотите точно знать, что делает ваш компилятор, попросите его исправить язык ассемблера (gcc -S).
Неопределенное поведение означает, что нет гарантии, что оно будет иметь конкретное поведение на любой платформе при любых условиях. У него нет никаких последствий, будете ли вы наблюдать за последовательным поведением между последовательными прогонами. – paddy
Он не определяется только потому, что он не изменяется для каждого запуска программы. – Pixelchemist
не определяется спецификацией языка, но компиляторы могут делать все, что им нравится. –