Инструменты пользователя

Инструменты сайта


// Гоняем структуры по сети

Вспоминаем о выравнивании (не говорю о том, что числовые поля нужно привести в сетевой вид, дабы на удаленной стороне была уже произведена корректная распаковка данных: man 3 htons/ntohs, man 3 htonl/htohl, man 3 endian), чешем репу - а если приёмная сторона использует другое выравнивание, нежели у нас при сборке бинарника?1)

Вижу варианты:

  • пихать все в char-буффер - некрасиво
  • поэлементно отправлять - неудобно и некрасиво
  • использовать #pragma pack() - удобно, красиво, но не супер переносимо
  • использовать систему атрибутов GCC - не переносимо

Посмотрим на использование #pragma pack(), конкретно посмотреть подробности на официальной странице: http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html

При объявлении структуры, которая будет гоняться по сети рекомендуется отключить выравнивание:

#pragma pack(push,1)
....
#pragma pack(pop)

Простой пример:

#include <stdio.h>
 
#pragma pack(push,1)
struct test_packed {
  char ch;
  long data;
};
#pragma pack(pop)
 
struct test_unpacked {
  char ch;
  long data;
};
 
int main()
{
  printf("Packed size: %d, Unpacked size: %d\n",
         sizeof(struct test_packed),
         sizeof(struct test_unpacked));
  return 0;
}

Компилируем и выполняем:

$ gcc -o main main.c && ./main
Packed size: 5, Unpacked size: 8

Всё наглядно :)

Не рекомендуется использовать для обычной работы: в размерах выигрыша почти не получится, а в скорости доступа проиграете.

UPD: тут #864110 подкинули ещё ссылку: http://www.leonerd.org.uk/code/libpack/

PS по слухам появилось в 2.95.2 или около того.

1)
по рабоче-крестьянски: на типичной 32бит машине все переменные выравнены по 32битной длинне

Комментарии