Доступ к памяти через указатели на структуры указателей - PullRequest
0 голосов
/ 08 декабря 2011

Предположим, у меня есть N байтов непрерывной памяти:

char A[N];

| | | | | | | | | | | | | | | | | | | |

, и я хочу получить доступ к памяти следующим образом:

|__ _|__ _| | | | | | | | | | | | | | |

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

Я пробовал этот способ, но он не работает:

typedef struct {
    int *a,*b;
    char *c;
} mem;

mem *p;
p->a=(int*)A;
p->b=((int*)A+1);
p->c=((int*)A+2);

или

mem *p
p=(mem*)A;

А затем получите доступ к элементам, используя *(p->a), *(p->b) и *(p->c).

Можете ли вы предложить мне правильный подход и объяснить, почему это не работает?

Ответы [ 4 ]

0 голосов
/ 08 декабря 2011

Это не работает, потому что методы хранения BYTE и DWORD в памяти разные (в архитектуре Intel).В то время как BYTE s сохраняются последовательно, DWORD s сохраняются в обратном порядке.Так что если вы хотите освободить скажем 1 как целое число (DWORD) из A[0], тогда A должно быть:

char A[]={1,0,0,0...}

Как я вижу, уже выложены правильные подходы.

0 голосов
/ 08 декабря 2011

Вы должны быть в состоянии сделать это следующим образом:

int* a;
int* b;
char* c;
char A[N] = {/* data goes here */};

a = (int*)A;
b = (int*)(A+sizeof(int));
c = A + 2*sizeof(int);

Обратите внимание, однако, что приведение типов между различными целочисленными типами, как это, не является четко определенным поведением в C. Код будет уязвим для порядка,нет никакого указания, где закончится бит со знаком, все это может привести к представлению прерывания и т. д. и т. д.

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

РЕДАКТИРОВАТЬ: Обратите внимание, что вышеприведенный способ является более переносимым, чем использование указателя структуры, хотя указатель структуры выглядит более элегантно.Поскольку структура может содержать любое количество байтов заполнения в любом месте, поэтому нет никаких гарантий, что указатель Struc поймет, что указанная память выделена смежно.

0 голосов
/ 08 декабря 2011

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

#include <stdio.h>

typedef struct {
   char block[4];
} block_of_4;

typedef struct {
   block_of_4 a;
   block_of_4 b;
   char c[1]; /* hack :) - more legal than "char c[0];" */
} mem;

int main(void)
{
   char A[] = "abcdefghijklmnopqrstuvwxyz";
   block_of_4 block1 = { { "1234" } };
   block_of_4 block2 = { { "9876" } };

   mem *p = (mem*) A;

   p->a = block1;
   p->b = block2;
   p->c[2] = '_';

   printf("%s\n", A);

   return 0;  
}

Выход:

12349876ij_lmnopqrstuvwxyz

Это до тех пор, пока компилятор решает поддерживать элементы struct в порядке и не выполняет никаких дополнений.

0 голосов
/ 08 декабря 2011

Попробуйте это:

#pragma pack(push)
#pragma pack(1)
 typedef struct {
     int a,b;
     char c[256]; // maximum length of `A`
 } mem;
#pragma pack(pop)

 mem *p = (mem*)A;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...