Определение, использует ли система Big Endian или Little Endian, используя C - PullRequest
2 голосов
/ 16 июля 2011

Мне любопытно, будет ли эта функция определять порядок байтов.

Тест является битовой маской, равной 1, если целое число someInt хранится в младшем порядке.

в битовой маске, будет ли 0x1000 преобразовываться в соответствии с порядком байтов машины или он будет "постоянным"?

#include <stdio.h>

int isBigEndian(){
    int someInt =0x0001;
    if(someInt & 0x0100 == 1) 
        return 1;
    else 
        return 0;
}

int main(){
    int returnVal = isBigEndian();
    printf("return val is %d", returnVal);
}

Ответы [ 5 ]

6 голосов
/ 16 июля 2011

Эта функция всегда будет возвращать ноль, поскольку ваши константы также хранятся в собственном порядке байтов системы. Намного лучше будет просто использовать системный API, который отвечает на ваш вопрос. Если вам нужно было быть переносимым, вы можете сравнить val == ntohl(val) для определения порядка байтов.

4 голосов
/ 16 июля 2011

Что бы я использовал, это:

union {
    short s;
    char b[2];
} endian;

endian.s = 1;
little_endian = endian.b[0] == 1;
2 голосов
/ 16 июля 2011

Строго говоря, единственный метод, который полностью совместим с ANSI C, - это перебирать все возможные значения int и проверять, все ли они соответствуют желаемому представлению. Тем не менее, если вы можете предположить, что все системы, в которых вы будете работать, имеют порядок с прямым или обратным порядком байтов или со смешанным порядком байтов (т. Е. Ничего странного, как кодирование с серым или BCD), вы можете просто сделать что-то вроде этого:

static const unsigned int testvec = 0x01020304;
static const unsigned char letest[4] = { 0x04, 0x03, 0x02, 0x01 };
static const unsigned char betest[4] = { 0x01, 0x02, 0x03, 0x04 };

int isle() {
  return !memcmp(&testvec, letest, 4);
}

int isbe() {
  return !memcmp(&testvec, betest, 4);
}

Обратите внимание, что если вы не смотрите на представление байтов (то есть, если вы не приводите указатели для просмотра необработанных байтов), вы не можете сказать, какой порядок байтов используется. 0x0001 & 0x1000 равно 0 во всех реализациях C, потому что и 0x0001, и 0x1000 одинаково заменены байтами (а также потому, что младшее порядковое представление 0x0001 равно 01 00, а не 10 00).

1 голос
/ 16 июля 2011

На этот вопрос есть несколько действительно хороших ответов (хотя это в контексте C ++ и C99);также ознакомьтесь с комментариями, они очень проницательны.

В Linux / Unix или любом другом, использующем glibc (mingw / cygwin), у вас также есть заголовочный файл endian.h с готовыми макросами,Вы также можете проверить реализацию 10000 * boost , которая является кроссплатформенной, чтобы получить советы по ее реализации самостоятельно, если хотите.

1 голос
/ 16 июля 2011

Лучше преобразовать значение типа int в типоразмер элементов sizeof (int). Посмотрите на это, чтобы увидеть, как оно выглядит.

Кроме того, ваш код зависит от очень sizeof(int). Ты не должен этого делать.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int a = 0xabcdef42;
    unsigned int i;
    char *s = calloc(sizeof(a) + 1, sizeof(s[0]));
    memcpy(s, &a, sizeof(a));
    printf("%x\n", a);
    for (i = 0; i < sizeof(a); i++)
        printf("%x ", (unsigned char)s[i]);
    printf("\n");
    free(s);
    return 0;
}

В результате (на моей машине установлен процессор Intel)

abcdef42
42 ef cd ab 

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...