В книге С.Прата. Язык программирования С представлен пример кода, который показывает что в определенных случаях даже с использованием правильного спецификатора возможен не тот результат который ожидался изначально*.
Вроде как общая логика понятна, но непонятны некоторые моменты в объяснении. Там приводится следующий пример:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <conio.h>
int main(void)
{
float a = 3.0;
double b = 3.0;
long c = 2000000000;
long d = 1234567890;
printf("%ld %ld %ld %ld", a, b, c, d);
_getch();
return 0;
}
И показываются результаты выполнения. Не совсем понятно откуда такой результат после объяснения. Там говорится что значения аргументов записываются в стек руководствуясь типами а не спецификаторами. Следовательно в стек сначала запишется "а" (64 бита), далее "b" (64 бита), потом "с" (32 бит) и в конце "d" (32 бита). Но при выводе, функция будет руководствоваться спецификаторами (везде %ld (32 бита)). Начнет считывать стек. Вот тут непонятно. Стек считывается как бы с конца, а спецификаторы записаны в порядке записи в стек аргументов. Вот встретился первый спецификатор, его нужно заменить на первый аргумент, но первым считываться из стека будет как раз таки последний аргумент. Вот этот момент не понятен, что происходит в момент считывания стека и замены спецификаторов.
Там представлена такая картинка. Она еще больше непонятностей создает. Вроде как запись в стек отображена правильно, а вот считывание непонятно, не с того конца началось. Получается что это и не стек вовсе а очередь.
В итоге у меня получилось что вещественные числа со спецификатором %ld вывелись как нули, а переменные с типом long, вывелись как надо. (В книге же результат получился таким: 0 неожиданное число 0 неожиданное число).
Что то все не сходится у меня в голове. Объяснение в книге, результат в книге и мои результаты, все отличается и не сходится.
Объясните пожалуйста работу данного примера, желательно бы с графическим представлением памяти.
PS. Используя разные компиляторы, получаются разные результаты вывода. Получается даже разная последовательность значений. В одном случае числа с типом long выводятся первыми, а далее неправильные значения чисел double. В другом же случае наоборот.
PSS. Вычитал что стандарт такое поведение не определяет. Но все равно хочется понять как все таки компиляторы обрабатывают данную ситуацию.