2013-04-10 3 views
3

Я мало знаю о указателях.Вывод программы-указателя

Я наткнулся на следующую программу. Выход кажется нормальным, но то, что на самом деле происходит, я не мог понять.

#include<stdio.h> 
#include<conio.h> 
void main() 
{ 
    int k; 
    int a[] = {1,2,3}; int *b[3] ; int **c[3]; 
    int ***d[3]; int ****e[3]; int*****f[3]; 
    for (k = 0 ; k <3; k++) 
    { 
     b[k] = a + k; c[k] = b + k ; d[k] = c + k; 
     e[k] = d + k ; f[k] = e + k; 

    } 
    for (k = 0 ; k <3; k++) 
    { 
     printf("%3d", *b[k]); printf("%3d", **c[k]); 
     printf("%3d", ***d[k]); printf("%3d", ****e[k]); 
     printf("%3d\n", *****f[k]); 
    } 
} 
+0

это домашнее задание или кто-то пытается совместить с вами? Избили этого парня, а затем ответьте на него :-) –

+0

Я нашел это на старых вопросах инженерного экзамена –

+0

да что объясняет :-) –

ответ

2

Первый цикл for - это просто базовая указательная арифметика. a[] содержит int, каждый массив после этого содержит указатель.
b[] является указателем на int
c[] является указателем на указатель на int
и т.д.

Так что-то вроде этого в памяти:

Memory Address:  0x00441234 <---+ 0x00441238 <----+  0x0044123C <---+ 
        **********  | **********  |  **********  | 
var name:   * a (+0) *  | * a (+1) *  |  * a (+2) *  | 
        **********  | **********  |  **********  | 
value:    * 1 *  | * 2 *  |  * 3 *  | 
        **********  | **********  |  **********  | 
            |     |     | 
            |     |     | 
        +-> 0x00442345 | +->0x00442349  | +->0x0044234D  | 
        | ************ | | ************ | | ************ | 
        | * b (+0) * | | * b (+1) * | | * b (+2) * | 
        | ************ | | ************ | | ************ | 
        | *0x00441234* -+ | *0x00441238* --+ | *0x0044123C* --+ 
        | ************ | ************  | ************  
        |     |     | 
        |     |     | 
        | 0x00443345  | 0x00443349  | 0x0044334D  
        | ************ | ************  | ************  
        | * c (+0) * | * c (+1) *  | * c (+2) *  
        | ************ | ************  | ************  
        +-- *0x00442345* +-*0x00442349*  +-*0x0044234D* 
         ************  ************  ************  

И каждый элемент D точек к каждому элементу C, и так далее. Конечным результатом является установка каждого элемента в каждом из массивов (через некоторую цепочку указателей) обратно на элементы a. А затем во втором цикле for вы снова и снова печатаете элементы a[].

+0

у вас 5-6 рук? и 5-6 клавиатур? :-) –

+0

@ Koushik У него, вероятно, есть [это] (http://www.asciiflow.com/#Draw). ;) –

+0

@SuvP oh wow thats хорошая ссылка. Благодарю. –

0

Вот что происходит:

Вы определяете переменную k типа данных int

Вы определяете массив, a, имеющие значения, 1, 2, 3

Вы определили массив указателей, b

Вы определили массив указателей на указатели, c

................................. и аналогичные ДО f

Вы итерацию от 0 до 2, и присвоены значения b, c, d, .... дО f

Вы снова итерация от 0 до 2 и напечатал:

значение указываемого каждым элементом в b , c, ..... до f

EDIT: Что случилось b [k] = a + k, вы перешли k блоков в свою память, адрес которых был назначен b [k]. Итак, b [k] указывает на этот блок в вашем (может быть любым значением)

+0

@Rohit: см. Правление – cipher

1
 int k; 
    int a[] = {1,2,3}; //array of 3 ints 
    int *b[3] ; //array of 3 integer pointers 
    int **c[3]; //array of 3 integer double pointers 
    int ***d[3]; //array of 3 pointers to integer double pointers 
    int ****e[3]; //array of 3 pointers to pointers to integer double pointers 
    int*****f[3]; //array of 3 pointers to pointers to pointers to integer double pointers 
    for (k = 0 ; k <3; k++) 
    { 
     b[k] = a + k; 
      //a gives base address to array a 
      //Add k to it and store it in b[k]. Note, this isn't normal arithmetic its 
      //pointer aritmetic 
     c[k] = b + k ; 
     d[k] = c + k; 
     e[k] = d + k ; 
     f[k] = e + k; 
    } 
    for (k = 0 ; k <3; k++) 
    { 
     printf("%3d", *b[k]); //dereference single level pointer 
     printf("%3d", **c[k]); //dereference second level pointer 
     printf("%3d", ***d[k]); printf("%3d", ****e[k]); 
     printf("%3d\n", *****f[k]); 
    } 

У вас может быть любое количество указателей уровня. то есть указатель на (указатель на (указатель ...)) и т. д. [до предела, определенного стандартами]

Для интересного чтения см. также this.

0

Сначала попытайтесь понять, что такое b[k] = a + k. остальные одинаковы.

a[] представляет собой массив с 3-х элементов 1, 2, and 3 и a сам по себе относятся к 0th элемента массива, т.е. a это адрес 1-го элемента массива.

a + k, в указателе арифметический, представляет элемент kth массива с именем a.

Итак, рассмотрим 1-ый проход цикла, и к = 0.

Ваше первое утверждение становится b[0] = a + 0. Уведомление a + 0 - это адрес, и он содержится в элементе b. Итак, b должен быть типа int *, а в вашем коде объявлено int *b[3].

И для c[0] = b + 0, вы храните address of address of int, поэтому c объявлен как двойной указатель int **c[3].

Теперь эти вещи случаются с каждым используемым вами массивом, только с дополнительным уровнем указателя. Это означает, что вы удерживаете адрес элементов предыдущего массива.

Смежные вопросы