манипулирование структурой указателя - PullRequest
0 голосов
/ 09 января 2010

Используемый код

#include<stdio.h>

struct st
{
 char a;
 short c;
 int b;
};

struct st s1;
int main()
{
        printf("%p %p \n",(&s1.b)-1, &s1);
}

Если я печатаю адрес &s1.b, он печатает 0x804a01c и &s1.b-2 печатает 0x804a018 почему он печатает тот же адрес 0x804a01c, если я выбираю &s1.b-1?

Ответы [ 4 ]

7 голосов
/ 09 января 2010

Возможно, что-то не так с вашим кодом печати. ​​

#include <stdio.h>

struct st
{
 char a;
 short c;
 int b;
};

struct st s1;

int main() {
    printf("%p\n", (void*)(&s1.b));
    printf("%p\n", (void*)(&s1.b - 1));
    printf("%p\n", (void*)(&s1.b - 2));
}

Выход:

0x403024
0x403020
0x40301c
2 голосов
/ 09 января 2010

Скорее всего, вы печатаете неправильно:

#include <stdio.h>

struct st
{
   char a;
   short c;
   int b;
};
struct st s;

int main(void)
{
    printf("s: %p\n", (void *)&s);
    printf("s.a: %p\n", (void *)&s.a);
    printf("s.b: %p\n", (void *)&s.b);
    printf("s.b-1: %p\n", (void *)(&s.b-1));
    printf("s.b-2: %p\n", (void *)(&s.b-2));
    return 0;
}

Отпечатки для меня:

s: 0x100001068
s.a: 0x100001068
s.b: 0x10000106c
s.b-1: 0x100001068
s.b-2: 0x100001064

На что обратить внимание:

  • Указатель на struct == указатель на первый элемент структуры (гарантируется стандартом C),
  • Я печатаю указатели со строкой формата "%p". "%p" требуется void *, а поскольку printf - это функция с переменным числом, в этом случае мне нужно привести аргументы к printf к void *.

Что печатает вышеприведенная программа для вас?

Редактировать : на основе фактического кода, опубликованного для печати, который вы опубликовали позже: вы не получаете одинаковое значение для &s1.b и &s1.b-1. Вы получаете одинаковое значение для &s1.b-1 и &s1. Ответ на этот вопрос: это происходит по случайности . В вашем случае это заполнение структуры, и sizeof(short)+sizeof(char) оказывается & le; sizeof(int). Если бы вы были на машине, где любое из этих предположений было недействительным, вы бы не увидели такого поведения. Я уверен, что если вы изменили char или short на int в своем коде, &s1.b-1 будет не равно &s1 при печати. ​​

Наконец, вы должны привести указатели к void * перед печатью:

printf("%p %p \n",(void *)((&s1.b)-1), (void *)&s1);
1 голос
/ 09 января 2010

Если адрес s1.b равен 0x804a01c, то & s1.b-2 должен быть 0x804a014 (при условии, что int равно 4 байта), а не 0x804a018. Возможно, вы допустили ошибку, сообщив адрес?

0 голосов
/ 10 января 2010

Спасибо за размещение вашего кода. Теперь я вижу проблему. Это из-за набивки. Для остроумия:

printf("sizeof(char): %d\n", sizeof(char));
printf("sizeof(short): %d\n", sizeof(short));
printf("sizeof(int): %d\n", sizeof(int));
printf("sizeof(struct st): %d\n", sizeof(struct st));

На моей машине это печатает

1
2
4
8

Вы можете подумать, разве sizeof(struct st) не должно быть 1 + 2 + 4 = 7? Это, конечно, разумная мысль, но из-за проблем с выравниванием между a и c есть отступы. Следовательно, в памяти структура выглядит следующим образом (относительно первого байта структуры):

0x00000000: char                 a
0x00000001: padding
0x00000002: first byte of short  c
0x00000003: second byte of short c
0x00000004: first byte of int    b
0x00000005: second byte of int   b
0x00000006: third byte of int    b
0x00000007: fourth byte of int   b

Следовательно (относительно &s1):

&s1.b - 1 is ((long)&s1.b) - sizeof(int) = 4 - 4 = 0 = &s1

Вот почему &s1 и &s1.b - 1 будут печатать один и тот же адрес. В частности, если

&s1 = 0x804a01c

тогда

&s1.b = 0x804a01c + 0x00000004 = 0x804a020

и

&s1.b - 1 = 0x804a020 - 0x00000004 = 0x804a01c

и

&s1.b - 2 = 0x804a020 - 0x00000008 = 0x804a018

Обратите внимание, наконец, что это поведение, зависящее от реализации. Это не портативный!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...