#c #c #arrays #integer #bit-manipulation
#c #c #массивы #целое число #манипулирование битами
Вопрос:
Я пытаюсь извлечь значения из массива uint8_t. Но у меня возникают проблемы с пониманием того, как они представлены в памяти.
#include <cstdio>
#include <cstring>
#include <stdint.h>
int main(){
uint8_t tmp1[2];
uint16_t tmp2 = 511;//0x01 0xFF = 0x01FF
tmp1[0] = 255;//0xFF
tmp1[1] = 1;//0x01
fprintf(stderr,"memcmp = %dn",memcmp(tmp1,amp;tmp2,2));
fprintf(stderr,"first elem in uint8 array = %un",(uint8_t) *(tmp1 0));
fprintf(stderr,"first elem in uint8 array = %un",(uint8_t) *(tmp1 1));
fprintf(stderr,"2xuint8_t as uint16_t = %un",(uint16_t) *tmp1);
return 0;
}
Итак, у меня есть массив данных типа uint8_t длиной в 2 элемента. И у меня есть единственная переменная uint16_t.
Поэтому, когда я беру значение 511 на моей маленькой конечной машине, я бы предположил, что это записано в памяти как
0000 0001 1111 1111
Но когда я использую memcompare, похоже, что он фактически представлен как
1111 1111 0000 0001
Так мало порядкового номера используется только «внутри» каждого байта?
И поскольку единственный бит, который установлен в tmp1 [1], считается равным 256, даже если он находится дальше «справа» в моем потоке. Следовательно, значения для каждого байта (не бита) являются бигендианскими? Я немного смущен этим.
Также, если я хочу принудительно распечатать fprint, мой 2xuint8_t как один uint16_t, как мне это сделать. Приведенный ниже код не работает, он распечатывает только первый байт.
fprintf(stderr,"2x uint8_t as uint16_t = %un",(uint16_t) *tmp1);
Заранее спасибо
Комментарии:
1. Процессор понимает, как сделать маленький порядковый номер, а вы нет.
2. @Patrick Это до тех пор, пока вы не общаетесь с другими машинами, которые имеют другой порядковый номер или просто выполняют хитроумные байтовые трюки. Хотя в большинстве случаев вам на самом деле не нужно беспокоиться об этом, это важно понимать и иметь в виду.
Ответ №1:
Ваше предположение о том, что вы ожидаете, обратное. Ваше наблюдение согласуется с представлением с малым порядковым номером. Чтобы ответить на ваш последний вопрос, это будет выглядеть так:
fprintf(stderr,"2x uint8_t as uint16_t = %un",*(uint16_t*)tmp1);
Ответ №2:
Не думайте о порядковости как о «в пределах байтов». Думайте об этом как о «упорядочении байтов». (То есть фактический порядок битов никогда не имеет значения, потому что люди обычно считывают значения в формате big-endian.) Если это помогает представить, что биты меняются местами на машине с малым порядком, вы можете представить это таким образом. (в этом случае ваш пример выглядел бы 1111 1111 1000 0000
так, но, как я уже сказал, люди обычно не читают числа так, чтобы наиболее значимые значения были справа … но вы можете представить, что именно так компьютер видит вещи, если это поможет вам понять строчный порядок.)
На маленькой конечной машине 0xAABBCCDD
это будет видно как 0xDD 0xCC 0xBB 0xAA
в памяти, так же, как вы видите. На машине с большим порядком (например, в PPC box) вы увидите тот же порядок в памяти, что и при записи 32-битного слова.
Ответ №3:
Во-первых, если вы хотите быть на 100% уверены, что ваши переменные хранятся в памяти в правильном порядке, вы должны поместить их в структуру.
Затем обратите внимание, что memcmp() обрабатывает вводимые вами данные как последовательность байтов, поскольку у него нет предположений относительно характера данных, которые вы ему предоставляете. Подумайте, например, о следующем коде:
#include <stdio.h>
#include <stdint.h>
int main(int argc, char** argv) {
int32_t a, b;
a = 1;
b = -1;
printf( "%in", memcmp( amp;a, amp;b, sizeof( int32_t ) ) );
}
Он выводит -254 на моей машине с малым порядковым номером независимо от того, что a> b . Это потому, что он не имеет представления о том, что такое память на самом деле, поэтому он сравнивает их как массив uint8_t .
Если вы действительно хотите визуализировать, как данные представлены на вашем компьютере, вы можете сначала использовать fwrite для записи структуры в файл, а затем открыть его с помощью вашего любимого шестнадцатеричного редактора (по моему опыту, wxHexEditor отлично показывает вам, как выглядят данные, если они имеют X-разрядный Y-конецingeter). Вот источник:
#include <stdio.h>
#include <stdint.h>
typedef struct {
uint8_t tmp1[2];
uint16_t tmp2;
} mytmp;
int main(int argc, char** argv) {
mytmp tmp;
tmp.tmp1[0] = 255;
tmp.tmp1[1] = 1;
tmp.tmp2 = 511;
FILE* file = fopen( "struct-dump", "w" );
fwrite( amp;tmp, sizeof( mytmp ), 1, file );
fclose( file );
}
Что касается обработки массива uint8_t как uint16_t , вы, вероятно, захотите объявить объединение или использовать принуждение указателя.