Могу ли я передать char, где в printf ожидается целое число?
Правильно ли указан следующий код?
char mychar = 200;
printf("%x", mychar);
Согласно http://www.cplusplus.com/reference/clibrary/cstdio/printf/ %x
ожидает целое число (4 байта с моим компилятором), и я прохожу только 1 байт. Поскольку printf
использует varargs, я опасаюсь, что это работает только из-за выравнивания байтов в стеке (т.е. char всегда использует 4 байта при нажатии в стеке).
Думаю, было бы лучше написать:
char mychar = 200;
printf("%x", static_cast<int>(mychar));
Как вы думаете, первый код в любом случае безопасен? Если нет, вы думаете, что я могу получить другой результат, если я перейду на архитектуру с бигеном?
Ответы
Ответ 1
В вашем примере аргумент имеет тип int
. mychar
повышается до int
из-за рекламных акций по умолчанию.
(C99, 6.5.2.2p6) "Если выражение, обозначающее вызываемую функцию, имеет тип, который не содержит прототип, то для каждого аргумента выполняются целые акции, а аргументы с типом float повышаются до двух. Они называются рекламными акциями по умолчанию."
и (внимание мое):
(C99, 6.5.2.2p7) " Если выражение, которое обозначает вызываемую функцию, имеет тип, который включает прототип,, аргументы неявно преобразуются, как если бы они были назначены, типам из соответствующих параметров, принимая тип каждого параметра в качестве неквалифицированной версии его объявленного типа. Обозначение многоточия в деклараторе прототипа функции приводит к тому, что преобразование типа аргумента останавливается после последнего объявленного параметра. Аргумент по умолчанию рекламные акции выполняются по завершающим аргументам."
Обратите внимание, что технически спецификатор преобразования x
требует аргумента unsigned int
, но int
и unsigned int
будут иметь одинаковое представление.
Ответ 2
Это работает только для вас, потому что ваша платформа способна интерпретировать int
(которому способствует ваш char
) как unsigned
, это то, что ожидает %x
. Чтобы быть уверенным, что это всегда работает, вы должны использовать и соответствующий спецификатор формата, а именно %d
.
Поскольку кажется, что вы хотите использовать char
в качестве числового количества, было бы лучше использовать два альтернативных типа signed char
или unsigned char
, чтобы ваше намерение было понятным. char
может быть подписанным или неподписанным типом на функции вашей платформы. Правильный спецификатор для unsigned char
будет тогда %hhx
.
Ответ 3
Если вы используете С++, вместо этого вы можете использовать потоки.
Вам нужно будет наложить символы на целые числа, иначе они будут напечатаны как глифы. Кроме того, подписанные символы будут расширены во время трансляции, поэтому лучше использовать unsigned char. Например, char, удерживающий 0xFF, будет печататься как 0xFFFFFFFF, если сначала не сбрасывается без знака char.
#include <iostream>
#include <iomanip>
int main(void){
char c = 0xFF;
std::cout << std::hex << std::setw(2) << std::setfill('0');
std::cout << static_cast<int>(static_cast<unsigned char>(c)) << std::endl;
return 0;
}
Ответ 4
Просто используйте printf ( "% hhx" , mychar). И, пожалуйста, не используйте cplusplus.com в качестве ссылки. Этот вопрос только доказывает, что его репутация содержит много ошибок и не содержит много информации.