Читать «UNIX: разработка сетевых приложений» онлайн - страница 62

Уильям Ричард Стивенс

В сетевом программировании наиболее общим примером аргумента типа «значение-результат» может служить длина возвращаемой структуры адреса сокета. Вы встретите и другие аргументы типа «значение-результат»:

■ Три средних аргумента функции select (раздел 6.3).

■ Аргумент «длина» для функции getsockopt (см. раздел 7.2).

■ Элементы msg_namelen и msg_controllen структуры msghdr при использовании с функцией recvmsg (см. раздел 14.5).

■ Элемент ifc_len структуры ifconf (см. листинг 17.1).

■ Первый из двух аргументов длины в функции sysctl (см. раздел 18.4).

3.4. Функции определения порядка байтов

Рассмотрим 16-разрядное целое число, состоящее из двух байтов. Возможно два способа хранения этих байтов в памяти. Такое расположение, когда первым идет младший байт, называется прямым порядком байтов (little-endian), а когда первым расположен старший байт — обратным порядком байтов (big-endian). На рис. 3.4 показаны оба варианта.

Рис. 3.4. Прямой и обратный порядок байтов для 16-разрядного целого числа

Сверху на этом рисунке изображены адреса, возрастающие справа налево, а снизу — слева направо. Старший бит (most significant bit, MSB) является в 16-разрядном числе крайним слева, а младший бит (least significant bit, LSB) — крайним справа.

ПРИМЕЧАНИЕ

Термины «прямой порядок байтов» и «обратный порядок байтов» указывают, какой конец многобайтового значения — младший байт или старший — хранится в качестве начального адреса значения.

К сожалению, не существует единого стандарта порядка байтов, и можно встретить системы, использующие оба формата. Способ упорядочивания байтов, используемый в конкретной системе, мы называем порядком байтов узла (host byte order). Программа, представленная в листинге 3.5, выдает порядок байтов узла.

Листинг 3.5. Программа для определения порядка байтов узла

//intro/byteorder.c

 1 #include "unp.h"

 2 int

 3 main(int argc, char **argv)

 4 {

 5  union {

 6   short s;

 7   char c[sizeof(short)];

 8  } un;

 9  un.s = 0x0102;

10  printf("%s: ", CPU_VENDOR_OS);

11  if (sizeof(short) == 2) {

12   if (un.c[0] == 1 && un.c[1] == 2)

13    printf("big-endian\n");

14   else if (un.c[0] == 2 && un.c[1] == 1)

15    printf("little-endian\n");