2010-01-09 2 views
0

Кодекс используетсяструктура указатель манипуляции

#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-20x804a018 печатает , почему он печатает тот же адрес 0x804a01c если я выбрать &s1.b-1?

+0

Наложение структуры определяется реализацией. –

+5

@Prasoon: это не имеет ничего общего с прокладкой структуры: '& s1.b' является' int * ', а отступы в структуре не влияют на то, как арифметика указателя работает с' int * '. –

+0

@Steve Jessop: Точно. Плюс один на ваш комментарий. – jason

ответ

0

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

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? Это, конечно, разумная мысль, но из-за alignment issues есть отступы между 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 

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

7

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

#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 
+0

Право: -1 или -2 раза sizeof (int) – stacker

+0

объявить структуру s1 глобально –

+2

@C Ученик: Объявление 's1' как глобального не изменит поведение (арифметика указателя определена очень четко, и нет никакой части спецификация, которая позволяет вмешиваться в детали, связанные с реализацией). – jason

1

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

+0

Вы имеете в виду 4 байта, а не 32 бит :-). 4 байта == 32 бит iff 'CHAR_BIT == 8'. –

+0

Конечно. Спасибо за исправление. – kusma

2

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

#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 

Things отметить:

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

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

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

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

printf("%p %p \n",(void *)((&s1.b)-1), (void *)&s1); 
Смежные вопросы