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- _______________________________________________ freebsd mailing list freebsd@uafug.org.ua http://mailman.uafug.org.ua/mailman/listinfo/freebsd