используя союз является чистым и легко
union
{
float f;
unsigned int ul;
unsigned char uc[4];
} myfloatun;
myfloatun.f=somenum;
printf("0x%08X\n",myfloatun.ul);
Гораздо безопаснее с точки зрения компилятора, чем указатели. Memcpy отлично работает.
EDIT
Хорошо, хорошо, здесь полностью функциональные примеры. Да, вы должны с осторожностью использовать профсоюзы, если не будете следить за тем, как этот компилятор выделяет союз и пэды или выравнивает его, что он может сломаться, и поэтому некоторые/многие говорят, что опасно использовать профсоюзы таким образом. Однако альтернативы считаются безопасными?
Проведение чтения С ++ имеет свои проблемы с профсоюзами, и объединение может очень просто не работать. Если вы действительно имели в виду C++, а не C, это, вероятно, плохо. Если вы сказали kleenex и означали ткани, тогда это может сработать.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef union
{
float f;
unsigned char uc[4];
} FUN;
void charRepresentation (unsigned char *uc, float f)
{
FUN fun;
fun.f=f;
uc[0]=fun.uc[3];
uc[1]=fun.uc[2];
uc[2]=fun.uc[1];
uc[3]=fun.uc[0];
}
void floatRepresentation (unsigned char *uc, float *f)
{
FUN fun;
fun.uc[3]=uc[0];
fun.uc[2]=uc[1];
fun.uc[1]=uc[2];
fun.uc[0]=uc[3];
*f=fun.f;
}
int main()
{
unsigned int ra;
float test;
char result[4];
FUN fun;
if(sizeof(fun)!=4)
{
printf("It aint gonna work!\n");
return(1);
}
test = 4.7567F;
charRepresentation(result,test);
for(ra=0;ra<4;ra++) printf("0x%02X ",(unsigned char)result[ra]); printf("\n");
test = 1.0F;
charRepresentation(result,test);
for(ra=0;ra<;ra++) printf("0x%02X ",(unsigned char)result[ra]); printf("\n");
test = 2.0F;
charRepresentation(result,test);
for(ra=0;ra<4;ra++) printf("0x%02X ",(unsigned char)result[ra]); printf("\n");
test = 3.0F;
charRepresentation(result,test);
for(ra=0;ra<4;ra++) printf("0x%02X ",(unsigned char)result[ra]); printf("\n");
test = 0.0F;
charRepresentation(result,test);
for(ra=0;ra<4;ra++) printf("0x%02X ",(unsigned char)result[ra]); printf("\n");
test = 0.15625F;
charRepresentation(result,test);
for(ra=0;ra<4;ra++) printf("0x%02X ",(unsigned char)result[ra]); printf("\n");
result[0]=0x3E;
result[1]=0xAA;
result[2]=0xAA;
result[3]=0xAB;
floatRepresentation(result,&test);
printf("%f\n",test);
return 0;
}
И результат выглядит следующим образом
gcc fun.c -o fun
./fun
0x40 0x98 0x36 0xE3
0x3F 0x80 0x00 0x00
0x40 0x00 0x00 0x00
0x40 0x40 0x00 0x00
0x00 0x00 0x00 0x00
0x3E 0x20 0x00 0x00
0.333333
Вы можете проверить вручную, или посмотреть на этом сайте, как я взял примеры непосредственно из него выход соответствует тому, что было ожидаемо.
http://en.wikipedia.org/wiki/Single_precision
То, что вы никогда не хотите сделать, это точка, в памяти с указателем, чтобы посмотреть на него с другим типом. Я никогда не понимал, почему эта практика используется так часто, особенно с помощью структур.
int broken_code (void)
{
float test;
unsigned char *result
test = 4.567;
result=(unsigned char *)&test;
//do something with result here
test = 1.2345;
//do something with result here
return 0;
}
Этот код будет работать в 99% случаев, но не в 100% случаев. Он потерпит неудачу, когда вы меньше всего этого ожидаете и в самое худшее время, как на следующий день после того, как ваш самый важный клиент получит его. Его оптимизатор, который ест ваш обед с этим стилем кодирования. Да, я знаю, что большинство из вас это делают, и их учили и, возможно, никогда не сжигали ....Это просто делает его более болезненным, когда он, наконец, происходит, потому что теперь вы знаете, что он может и не справился (с популярными компиляторами, такими как gcc, на обычных компьютерах, таких как ПК).
После того, как этот метод был неудачным при использовании этого метода для тестирования fpu, программно построив определенные числа/шаблоны с плавающей запятой, я переключился на союзный подход, который до сих пор не сработал. По определению элементы в объединении имеют один и тот же кусок хранилища, а компилятор и оптимизатор не путаются в отношении двух элементов в этом общем хранилище, которые ... находятся в том же разделяемом хранилище. С помощью вышеприведенного кода вы полагаетесь на предположение, что за каждым использованием переменных сохраняется нерегистровая память, а все переменные записываются обратно в эту память перед следующей строкой кода. Отлично, если вы никогда не оптимизируете или используете отладчик. Оптимизатор в этом случае не знает, что результат и тест имеют один и тот же кусок памяти, и это корень проблемы/ошибки. Чтобы сделать игру с указателем, вы должны попасть во все, что угодно, как союз, вам все равно нужно знать, как компилятор выравнивает и прокладывает подушки, вам все равно придется иметь дело с контентами.
Проблема заключается в том, что компилятор не знает, что два элемента имеют одинаковое пространство памяти. Для конкретного тривиального примера выше я наблюдал, как компилятор оптимизирует присвоение числа переменной с плавающей запятой, поскольку это значение/переменная никогда не используется. Адрес для хранения этой переменной используется, и если вы скажете printf данные результата *, компилятор не будет оптимизировать указатель результата и, таким образом, не будет оптимизировать адрес для тестирования и, таким образом, не будет оптимизировать хранилище для теста, но в этом простом примере он может и произошел, когда числа 4.567 и 1.2345 никогда не попадают в скомпилированную программу. Я также вижу, что компилятор выделяет хранилище для теста, но присваивает числа регистру с плавающей запятой, а затем никогда не использует этот регистр и не копирует содержимое этого регистра в хранилище, которое он назначил. Причин, по которым он не подходит для менее простых примеров, может быть труднее следовать, что часто связано с распределением регистров и выселением, изменяет строку кода и работает, меняет другую, и она ломается.
тетсру,
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void charRepresentation (unsigned char *uc, float *f)
{
memcpy(uc,f,4);
}
void floatRepresentation (unsigned char *uc, float *f)
{
memcpy(f,uc,4);
}
int main()
{
unsigned int ra;
float test;
unsigned char result[4];
ra=0;
if(sizeof(test)!=4) ra++;
if(sizeof(result)!=4) ra++;
if(ra)
{
printf("It aint gonna work\n");
return(1);
}
test = 4.7567F;
charRepresentation(result,&test);
printf("0x%02X ",(unsigned char)result[3]);
printf("0x%02X ",(unsigned char)result[2]);
printf("0x%02X ",(unsigned char)result[1]);
printf("0x%02X\n",(unsigned char)result[0]);
test = 0.15625F;
charRepresentation(result,&test);
printf("0x%02X ",(unsigned char)result[3]);
printf("0x%02X ",(unsigned char)result[2]);
printf("0x%02X ",(unsigned char)result[1]);
printf("0x%02X\n",(unsigned char)result[0]);
result[3]=0x3E;
result[2]=0xAA;
result[1]=0xAA;
result[0]=0xAB;
floatRepresentation(result,&test);
printf("%f\n",test);
return 0;
}
gcc fcopy.c -o fcopy
./fcopy
0x40 0x98 0x36 0xE3
0x3E 0x20 0x00 0x00
0.333333
С пламенным я собираюсь получить о моих вышеизложенных замечаний, и в зависимости от того, какая сторона аргумента вы решили быть. Возможно, memcpy - ваш самый безопасный маршрут. Вы все еще должны хорошо знать компилятор и управлять своими контентами. Компилятор не должен испортить memcpy, он должен хранить регистры в памяти до вызова и выполнять в порядке.
Какое значение вы ожидаете от 'результата'? –
То есть, чего вы пытаетесь достичь? – Potatoswatter
Поплавок уже в «двоичном», между прочим. По крайней мере, с учетом любого практического компьютера, который использует OP. –