Требуется обходной путь Endianness

Рассмотрим следующий фрагмент кода:

#include "stdio.h"
typedef struct CustomStruct
{
short Element1[10];
}CustomStruct;

void F2(char* Y)
{
*Y=0x00;
Y++;
*Y=0x1F;
}

void F1(CustomStruct* X)
{
F2((char *)X);
printf("s = %x\n", (*X).Element1[0]);
}

int main(void)
{
CustomStruct s;
F1(&s);

return 0;
}

Во время выполнения, к концу вызова функции F1Я получаю разные результаты, используя разные компиляторы.

(*X).Element1[0] = 0x1f00 в каком-то компиляторе и (*X).Element1[0] = 0x001f с другим.

Мне ясно, что это проблема порядка байтов.

Есть ли какая-либо опция компилятора или обходной путь, чтобы использовать, чтобы я получил (*X).Element1[0] = 0x001f независимо от используемого компилятора?

0

Решение

Порядок байтов это не проблема компилятора и даже не проблема операционной системы, а проблема платформы. Здесь нет опций компилятора или «обходных путей» для порядка байтов. Однако существуют процедуры преобразования, чтобы вы могли нормализовать порядок сохраненных данных.

ntoh подпрограммы задокументировано здесь будет переупорядочивать байты, на которые указывает сетевой порядок (с прямым порядком байтов), на порядок хостов (большой или маленький, в зависимости от типа хоста). Это также hton функции, которые идут в обратном направлении, от порядка хоста до порядка сети.

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

Вот шаблоны функций, для которых я написал ntohx а также htonx которые обобщены на типе хранилища данных, будь то 2 байта, 4 байта или 8 байтов:

template<class Val> inline Val ntohx(const Val& in)
{
char out[sizeof(in)] = {0};
for( size_t i = 0; i < sizeof(Val); ++i )
out[i] = ((char*)&in)[sizeof(Val)-i-1];
return *(reinterpret_cast<Val*>(out));
}

template<> inline unsigned char ntohx<unsigned char>(const unsigned char & v )
{
return v;
}
template<> inline uint16_t ntohx<uint16_t>(const uint16_t & v)
{
return ntohs(v);
}

template<> inline uint32_t ntohx<uint32_t>(const uint32_t & v)
{
return ntohl(v);
}

template<> inline uint64_t ntohx<uint64_t>(const uint64_t & v)
{
uint32_t ret [] =
{
ntohl(((const uint32_t*)&v)[1]),
ntohl(((const uint32_t*)&v)[0])
};
return *((uint64_t*)&ret[0]);
}
template<> inline float ntohx<float>(const float& v)
{
uint32_t const* cast = reinterpret_cast<uint32_t const*>(&v);
uint32_t ret = ntohx(*cast);
return *(reinterpret_cast<float*>(&ret));
};

template<class Val> inline Val htonx(const Val& in)
{
char out[sizeof(in)] = {0};
for( size_t i = 0; i < sizeof(Val); ++i )
out[i] = ((char*)&in)[sizeof(Val)-i-1];
return *(reinterpret_cast<Val*>(out));
}

template<> inline unsigned char htonx<unsigned char>(const unsigned char & v )
{
return v;
}
template<> inline uint16_t htonx<uint16_t>(const uint16_t & v)
{
return htons(v);
}

template<> inline uint32_t htonx<uint32_t>(const uint32_t & v)
{
return htonl(v);
}

template<> inline uint64_t htonx<uint64_t>(const uint64_t & v)
{
uint32_t ret [] =
{
htonl(((const uint32_t*)&v)[1]),
htonl(((const uint32_t*)&v)[0])
};
return *((uint64_t*)&ret[0]);
}
template<> inline float htonx<float>(const float& v)
{
uint32_t const* cast = reinterpret_cast<uint32_t const*>(&v);
uint32_t ret = htonx(*cast);
return *(reinterpret_cast<float*>(&ret));
};
6

Другие решения

Если F2() получает char *тогда он должен делать что-то довольно странное, чтобы вызвать проблемы, связанные с порядком байтов.

Это происходит только при доступе Больше чем один char за раз, если только он не делает такие доступы вручную, будучи взломанным. Приводит ли этот аргумент к short * или что-то?

Короче, покажи больше кода.

2