/ / Qual é o caminho mais rápido para alternar o endianness ao ler um arquivo com C ++? - c ++, performance, arquivo, endianness

Qual é o caminho mais rápido para alternar o endianness ao ler de um arquivo com C ++? - c ++, performance, arquivo, endianness

Eu tenho fornecido um arquivo binário para ler, quecontém uma sequência de valores brutos. Por uma questão de simplicidade, suponha que eles "não tenham valores integrais, de 4 bytes ou 8 bytes. Infelizmente para mim, a ordem de bytes para esses valores é incompatível com o endianness de meu processador (pouco contra grande ou vice-versa); não se preocupe com a estranheza do PDF-endianness etc.); e quero esses dados na memória com o endianness adequado.

Qual é a maneira mais rápida de fazer isso, considerando o fato de que estou lendo os dados de um arquivo? Se não vale a pena explorar este fato, por favor, explique por que isso é.

Respostas:

2 para resposta № 1

Considerando o fato de que você está lendo os dados de um arquivo, a forma como você alterna o endianness terá um efeito insignificante no tempo de execução, comparado com o que o file-IO faz.

O que poderia fazer uma diferença significativa é comovocê lê os dados. Tentar ler os bytes fora de ordem não seria uma boa ideia. Simplesmente leia os bytes em ordem e mude o endianness depois. Isso separa a leitura e a troca de bytes.

o que Eu Quer o código de troca de byte normalmente e, certamente, em um caso de leitura de um arquivo, é que ele funciona para qualquer fim de vida e não depende de instruções específicas de arquitetura.

char* buf = read(); // let buf be a pointer to the read buffer
uint32_t v;

// little to native
v = 0;
for(unsigned i = 0; i < sizeof v; i++)
v |= buf[i] << CHAR_BIT * i;

// big to native
v = 0;
for(unsigned i = 0; i < sizeof v; i++)
v |= buf[i] << CHAR_BIT * (sizeof v - i);

Isso funciona se o nativo é grande, pequeno ou um dos tipos de endívia média.

Claro, impulso já implementou estes para você, então não há necessidade de re-implementar. Além disso, existem os ntoh? família de funções fornecidas pelo POSIX e pela biblioteca windows C, que pode ser usada para converter big endian de / para nativo.


1 para resposta № 2

Não é o mais rápido, mas uma maneira portátil seria ler o arquivo em uma matriz int (não assinada), alias a matriz int a uma char (permitida por regra de aliasing estrita) e trocar bytes na memória.

Maneira totalmente portátil:

swapints(unsigned int *arr, size_t l) {
unsigned int cur;
char *ix;
for (size_t i=0; i<l; i++) {
int cur;
char *dest = static_cast<char *>(&cur) + sizeof(int);
char *src = static_cast<char *>(&(arr[i]));
for(int j=0; j<sizeof(int); j++) *(--dest) = *(src++);
arr[i] = cur;
}
}

Mas se você não precisa de portabilidade, alguns sistemas oferecem funções de troca. Por exemplo, os sistemas BSD bswap16, bswap32 e bswap64 trocar byte em uint16_t, uint32_t e uint_64_t respectivamente. Sem dúvida existem funções equivalentes nos mundos Microsoft ou GNU-Linux.

Como alternativa, se você sabe que o arquivo está em rede ordem (big endian) e seu processador não é, você pode usar o ntohs e ntohl funções para respectivamente uint16_t e uint32_t.

Comentário (de acordo com Andrew Henle): seja qual for a host endianness, ntohs e ntohl sempre pode ser usado - simplesmente eles não são operados em sistemas big-endian