2013-10-05 3 views
1

Является ли это безопасным способом преобразования массива в число?Преобразование массива символов в int в C

// 23 FD 15 94 -> 603788692 
char number[4] = {0x94, 0x15, 0xFD, 0x23}; 
uint32_t* n = (uint32_t*)number; 
printf("number is %lu", *n); 

ПОДРОБНЕЕ

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

+0

No..safe and better is 'char * n = number;' –

+2

Это зависит от того, что вы можете сделать, так как у вас могут возникнуть проблемы с рецепцией. и ..._ t имеют специальные форматы printf. –

ответ

3

Нет. Доступно только что-то в виде целого числа, если оно равно целое число.

Но вот как вы можете манипулировать бинарное представление объекта, просто поворачивая логику вокруг:

uint32_t n; 

unsigned char * p = (unsigned char *)&n; 

assert(sizeof n == 4); // assumes CHAR_BIT == 8 

p[0] = 0x94; p[1] = 0x15; p[2] = 0xFD; p[3] = 0x23; 

Мораль: Вы можете рассматривать каждый объект в виде последовательности байтов, но вы не можете лечить произвольная последовательность байтов как любой конкретный объект.

Кроме того, двоичное представление типа очень важно зависит от платформы, поэтому нет информации о том, какое фактическое целочисленное значение вы получите из этого. Если вы просто хотите, чтобы синтезировать целое значение от его базовых 256 цифр, используйте обычную математику:

uint32_t n = 0x94 + (0x15 * 0x100) + (0xFD * 0x10000) + (0x23 * 0x1000000); 

Это полностью зависит от платформы и выражает то, что вы хотите, чисто с точкой зрения значений, а не представление. Оставьте его компилятору для представления машинного представления кода.

+2

Работает только на архитектуре LSB. – willus

+0

@willus: Определить «работает» :-) Я добавил то, что, по моему мнению, является «реальным» решением проблемы OP. –

+0

@willus: OP * заверил * нас/он на архитектуре LSB. Даже «n [0] + (n [1] << 8) + ..» делает предположение о контен- тальности. – usr2564301

3

Нет, это не безопасно.

Это нарушает правила сглаживания С, которые говорят, что к объекту можно получить доступ только через его собственный тип, его подписанный/неподписанный вариант или через характер. Он также может вызывать неопределенное поведение, нарушая выравнивание.

безопасное решение, чтобы получить значение uint32_t из массива является использование битовых операторов (<< и &) на char значений для формирования uint32_t.

+0

и safe is 'char * n = number;' :) –

+0

Я попытался получить предупреждение с 'gcc' (' -Wstrict-aliasing -fstrict-aliasing'), но он ничего не сообщает. Есть ли способ поймать это? –

+1

@KarolyHorvath в моей системе 'gcc' дает мне предупреждение с псевдонимом с' -Wstrict-aliasing = 2'. В любом случае '-Wstrict-aliasing' является наилучшим усилием и не гарантированно перехватывает все переходы на псевдонимы. – ouah

0

Ты лучше с чем-то вроде этого (более портативный):

int n = (c[3]<<24)|(c[2]<<16)|(c[1]<<8)|c[0]; 

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

Смежные вопросы