[freebsd] printf в clang

Valentin Nechayev netch at netch.kiev.ua
Thu Dec 30 23:39:04 EET 2021


hi,

 Thu, Dec 30, 2021 at 21:15:36, spell wrote about "[freebsd] printf в clang": 

> int64_t bv;
> long cid;
> bv = ( (int64_t) 1 << 33) + 3;
> cid = 111;
> printf("%ld %ldn", bv, cid);

Тут наверно должно было быть \n в конце форматной строки.

> clang резонно выдает варнинг о несоответствии типа первого аргумента (%ld вместо правильного %lld).

Компиляция в 32 битах, я так понимаю? Потому что в 64 проблем не
видно.

> А вот вывод этой программы менее ожидаем:
> 
> 3 2
> 
> Первое число ожидаемо - младшие 4 байта от bv.
> А второе, вместо значения cid - старшие 4 байта от bv.
> 
> clang version 10.0.1.

Именно что если в 32 битах, то всё логично, потому что:
1. При передаче в переменном наборе аргументов (как printf) происходит
расширение всех целочисленных типов, которые у́же int, к int, а более
широкие не меняются.
2. Соглашение о вызове предусматривает передачу всех аргументов на
стеке. Соответственно в позиции начала переменной области аргументов
укладывается: 03 00 00 00 02 00 00 00 (bv) 6f 00 00 00 (cid).
3. printf согласно формату %ld извлекает long, который в этом режиме
32 бита (равен int). Извлекается 03 00 00 00 (значение 3).
Второй %ld извлекает 02 00 00 00 (значение 2).

В 64 битах проблемы не будет, потому что:

1. Первые 6 аргументов передаются в регистрах, включая переменные
аргументы (! - из-за этого va_arg c компанией заметно усложняется).
Форматная строка будет в rdi, bv - в rsi, cld - в rdx.
2. long и long long одинаково имеют 64 бита ширины и передаются
соответственно в полную ширину регистра.

Хорошо, что оно ворнинги пишет :))


-netch-


More information about the freebsd mailing list