Typecasting структуры для получения отдельных адресов полей - PullRequest
1 голос
/ 31 августа 2011
#include<stdio.h>
#include<stdlib.h>
struct test{
    char b;
    int a;
    int c ; 
    };
int main()
{
    struct test inst;
    struct test *ptr_test = &inst;
    char * ptr_ch;
    int* ptr_i;

    /*ptr_ch = (char *) ptr_test;*/
    ptr_ch = (char*)ptr_test;
    ptr_i = (int *) ptr_test;
    *ptr_ch = 'b';
    *ptr_i = 13; 

    printf("char b = %c, int a = %d int c = %d", inst.b, inst.a, inst.c);

    return 0;
}

Я ожидал, что результат выдаст соответствующие значения a, b и значение мусора c. Но на терминале, если я это сделаю ./a.out вывод:

, int a = 134513785 int c = 13173540

Когда я делаю $. / A.out> tmp; vim tmp, вывод:

char b = ^ M, int a = 134513785 int c = 12714788

В чем проблема?

Я хотел получить доступ к отдельным полям структуры, используя приведение типов.

например, я хотел знать другой способ вернуть значение & (inst.a).

Ответы [ 5 ]

2 голосов
/ 31 августа 2011

Ваши указатели

ptr_ch = (char*)ptr_test;
ptr_i = (int *) ptr_test;

не ссылаются автоматически на первую подходящую переменную-член (в вашем случае b и a).Скорее они просто интерпретируют указатель на структуру как указатель на char или int, поэтому они указывают на то же местоположение, адрес вашей структуры.С char вам может повезет, что это первый участник, и вы действительно указываете на char, но ваш указатель int указывает на тот же адрес и поэтому перезаписывает его платформой -зависящий от компилятора мусор.

Так что не делайте таких вещей (или делайте это, когда вы действительно знаете, что делаете, и, что более важно, где (на какой платформе икакой компилятор) ты это делаешь).

1 голос
/ 31 августа 2011

ptr_ch и ptr_i указывают на одну и ту же ячейку памяти:

ptr_ch = (char*)ptr_test;
ptr_i = (int *) ptr_test;

когда вы делаете следующее, вы читаете с одного и того же адреса памяти:

*ptr_ch = 'b'; //write the first sizeof(char) byte of the structure ptr_test
*ptr_i = 13;   //write the first sizeof(int) bytes of the structure ptr_test overwriting some bytes wrote before

В конечном итоге вы должны что-то сделатькак:

ptr_ch = &(ptr_test->b);
*ptr_ch = 'b';
ptr_i = &(ptr_test->a);
*ptr_i = 13; 
0 голосов
/ 31 августа 2011

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

 ptr_ch = (char*)ptr_test;
*ptr_ch = 'b';

 ptr_i = ptr_ch + offsetof(struct test,a);
*ptr_i = 13; 
 ptr_i = ptr_ch + offsetof(struct test,c);
*ptr_i = 14; 
0 голосов
/ 31 августа 2011

13 является десятичным для возврата каретки ASCII - когда вы делаете *ptr_i = 13;, вы устанавливаете b на 13. Если вы измените свой отпечаток так, чтобы он выглядел как:

printf("char b = %c (%d), int a = %d int c = %d", inst.b, inst.b, inst.a, inst.c);

Вы увидите, что вы получите:

(13), int a = 1 int c = 1606416024

вместо вывода. Символ возврата каретки приводит к тому, что ваш вывод char b перезаписывается выводом после символа возврата каретки. Это может быть более очевидно, если вы использовали другое число, отличное от 13. Например, используя 86, вы получите:

char b = V, int a = 1 int c = 1606416024

в качестве вывода. Причина a и c не имеет смысла в том, что они неинициализированы.

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

ptr_ch = &ptr_test->b;
ptr_i = &ptr_test->a;

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

#include<stdio.h>

struct test {
  char b;
  int a;
  int c; 
};

int main(void)
{
  struct test inst = {0, 0, 0};
  struct test *ptr_test = &inst;
  char *ptr_ch;
  int *ptr_i;

  ptr_ch = &ptr_test->b;
  ptr_i = &ptr_test->a;
  *ptr_ch = 'b';
  *ptr_i = 86; 

  printf("char b = %c, int a = %d int c = %d\n", inst.b, inst.a, inst.c);

  return 0;
}

И его вывод:

char b = b, int a = 86 int c = 0
0 голосов
/ 31 августа 2011

Зачем вам использовать приведение типов?Почему бы не сделать следующее:

ptr_ch = &(ptr_test->b);
ptr_i = &(ptr_test->a);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...