порядковый номер при использовании части массива int - PullRequest
1 голос
/ 24 октября 2011

Я пытаюсь извлечь значения из массива 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 = %d\n",memcmp(tmp1,&tmp2,2));


  fprintf(stderr,"first elem in uint8 array  = %u\n",(uint8_t) *(tmp1+0));
  fprintf(stderr,"first elem in uint8 array  = %u\n",(uint8_t) *(tmp1+1));

  fprintf(stderr,"2xuint8_t as uint16_t  = %u\n",(uint16_t) *tmp1);
  return 0;
}

Итак, у меня есть массив из 2 элементов с типом данных uint8_t.И у меня есть единственная переменная uint16_t.Поэтому, когда я принимаю значение 511 на моей машине с прямым порядком байтов, я предполагаю, что это расположено в памяти как

0000 0001 1111 1111

Но когда я использую memcompare, похоже, что оно действительно представляется как

1111 1111 0000 0001 

Так мало ли порядка байтов используется только "внутри" каждого байта?И так как единственный бит, который установлен в tmp1 [1], считается как 256, даже если он еще «прав» в моем потоке.Значения для каждого байта (не бит), следовательно, является бигендианским?Я немного запутался по этому поводу.

Также, если я хочу принуждать отпечаток, распечатать, мой 2xuint8_t как один uint16_t, как мне это сделать.Приведенный ниже код не работает, он только распечатывает первый байт.

fprintf(stderr,"2x uint8_t as uint16_t  = %u\n",(uint16_t) *tmp1);

Заранее спасибо

Ответы [ 3 ]

4 голосов
/ 24 октября 2011

Ваше предположение о том, что вы ожидаете, обратное. Ваше наблюдение соответствует представлению с прямым порядком байтов. Чтобы ответить на ваш последний вопрос, это выглядело бы так:

fprintf(stderr,"2x uint8_t as uint16_t  = %u\n",*(uint16_t*)tmp1);
1 голос
/ 24 октября 2011

Не думайте о порядке байтов как "в байтах". Думайте об этом как "порядок байтов". (То есть фактическое упорядочение битов никогда не имеет значения, потому что люди обычно читают значения с прямым порядком байтов.) Если это помогает представить, что биты обращаются на машине с прямым порядком байтов, вы можете представить это таким образом. (в этом случае ваш пример выглядел бы как 1111 1111 1000 0000, но, как я уже сказал, люди обычно не читают цифры так, что наиболее значимые значения находятся справа ... но вы можете представить, что именно так компьютер видит вещи, если это поможет вам понять little-endian.)

На машине с прямым порядком байтов 0xAABBCCDD будет выглядеть как 0xDD 0xCC 0xBB 0xAA в памяти, так же, как вы видите. На машине с прямым порядком байтов (такой как PPC-блок) вы увидите тот же порядок в памяти, что и при записи 32-битного слова.

1 голос
/ 24 октября 2011

Во-первых, если вы хотите быть на 100% уверены, что ваши переменные хранятся в правильном порядке в памяти, вы должны поместить их в структуру.

Затем обратите внимание, что memcmp () обрабатывает ввод, который вы даете ему, какпоследовательность байтов, поскольку в ней нет предположений относительно характера данных, которые вы ей предоставляете.Подумайте, например, о следующем коде:

#include <stdio.h>
#include <stdint.h>

int main(int argc, char** argv) {
    int32_t a, b;
    a = 1;
    b = -1;
    printf( "%i\n", memcmp( &a, &b, sizeof( int32_t ) ) );
}

Он выдает -254 на моей машине с прямым порядком байтов, независимо от того, что a> b.Это потому, что он не имеет представления о том, что на самом деле является памятью, поэтому он сравнивает их как массив uint8_t.

Если вы действительно хотите визуализировать, как данные представлены на вашем компьютере, вы можете сначала использовать fwriteзаписать структуру в файл, а затем открыть ее с помощью вашего любимого шестнадцатеричного редактора (по моему опыту, wxHexEditor замечательно рассказывает вам, как выглядят данные, если они являются X-битным Y-порядковым входным механизмом).Вот источник:

#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( &tmp, sizeof( mytmp ), 1, file );
    fclose( file );
}

Что касается обработки массива uint8_t как uint16_t, вы, вероятно, захотите объявить union или использовать приведение указателя.

...