В таком случае std :: initializer_list - лучший выбор.
class Foo{
public:
Foo(int n, std::initializer_list a, std::initializer_list b);
};
Foo foo { 32, {}, { 2, 3, 1, 2 }};
x
спецификатор формата отдельно говорит, что аргумент int
, и так как число отрицательно, printf
требует, чтобы восемь символов показали все четыре ненулевых байта int
- размерное значение. 0
модификатор говорит для заполнения вывода нулями, и 2
модификатор говорит, что минимальный вывод должен быть двумя символами долго. Насколько я могу сказать, printf
не позволяет указывать максимальную ширину, за исключением строк.
Теперь затем Вы только передаете a char
, таким образом пустой x
говорит функции использовать полное int
это было передано вместо этого — из-за продвижения параметра по умолчанию для"...
"параметры. Попробуйте hh
модификатор, чтобы сказать функции рассматривать аргумент как просто a char
вместо этого:
printf("%02hhx", b[i]);
символ является типом со знаком; таким образом с дополнением two, 0x80-128 для 8-разрядного целого числа (т.е. байт)
То, что Вы видите, является преобразованием сохранения знака от символа до интервала. Поведение следует из того, что в Вашей системе, символ подписывается (Примечание: символ не подписывается во всех системах). Это приведет к отрицательным величинам, если комбинация двоичных разрядов уступит отрицательной величине для символа. Продвижение такого символа к интервалу сохранит знак, и интервал будет отрицателен также. Обратите внимание на это, даже если Вы не помещаете a (int)
явно, компилятор будет автоматически способствовать символу интервал при передаче printf. Решение состоит в том, чтобы преобразовать Ваше значение в unsigned char
во-первых:
for (i=0; i<4; i++)
printf("%02x ", (unsigned char)b[i]);
С другой стороны, можно использовать unsigned char*
от запуска на:
unsigned char *b = (unsigned char *)&a;
И затем Вам не нужен никакой бросок в то время, когда Вы печатаете его с printf.
Обработка Вашей структуры, как будто это был массив символов, является неопределенным поведением. Для отправки его по сети используйте надлежащую сериализацию вместо этого. Это - боль в C++ и еще больше в C, но это - единственный способ, которым Ваше приложение будет работать независимо от чтения машин и записи.
символ является типом со знаком поэтому, что Вы видите, представление с двумя комплиментами, бросание к (неподписанный символ*) зафиксирует это (Rowland просто победил меня).
На стороне отмечают, что можно хотеть измениться
for (i=0; i<4; i++) {
//...
}
кому:
for (i=0; i<sizeof(x); i++) {
//...
}
Можно хотеть преобразовать в неподписанный массив символов.
Если у Вас нет очень убедительных измерений, показывающих, что каждый октет драгоценен, не делайте этого. Используйте читаемый протокол ASCII как SMTP, NNTP или один из многих других прекрасных Протоколов Интернета, шифруемых IETF.
Если у Вас действительно должен быть двоичный формат, все еще не безопасно только вытолкать байты в структуре, потому что порядок байтов, основные размеры или ограничения выравнивания могут отличаться от хоста до хоста. Необходимо разработать провод protcol, чтобы использовать четко определенные размеры и использовать четко определенный порядок байтов. Для Вашей реализации, любых макросов использования как ntohl(3)
или используйте смещение и маскирование для помещения байтов в поток. Независимо от того, что Вы делаете, удостоверьтесь, что Ваш код приводит к тем же результатам и на хостах с прямым порядком байтов и на с обратным порядком байтов.
При преобразовании структуры в символы или байты путем, Вы делаете его, собирается привести к проблемам, когда Вы действительно пытаетесь сделать это сетью нейтральный. Почему бы не решить ту проблему теперь? Существует множество различных методов, которые можно использовать, все из которых, вероятно, будут более "портативными", чем, что Вы пытаетесь сделать. Например:
htonl
, htons
, ntohl
и ntohs
. Посмотрите, например, byteorder (3) страница руководства в системе FreeBSD или Linux.Когда вы собираетесь отправить его, просто используйте:
(char *) & CustomPacket
для преобразования. Работает для меня.
Знаковость массива char не является корнем проблемы! (Это -а-проблема, но не единственная проблема.)
Выравнивание! Это ключевое слово здесь. Вот почему вы НИКОГДА не должны пытаться обращаться со структурами как с необработанной памятью. Компиляторы (и различные флаги оптимизации), операционные системы, фазы луны - все это делает странные и интересные вещи с фактическим расположением в памяти "соседних" полей в структуре. Например, если у вас есть структура с char, за которой следует int, вся структура будет занимать в памяти ВОСЕМЬ байт - char, 3 пустых, бесполезных байта, а затем 4 байта для int. Машине нравится делать такие вещи, чтобы структуры умещались на страницах памяти, и тому подобное.
Пройдите вводный курс по архитектуре машины в местном колледже. Между тем, сериализуйте правильно. Никогда не обращайтесь со структурами как с массивами char.