Одинарный или двойной указатель в C - PullRequest
0 голосов
/ 25 февраля 2020

Уже этот вопрос задают здесь: двойной указатель против одного указателя

Я следовал инструкциям этого вопроса, но столкнулся с ошибками и все еще не в состоянии точно понять, что происходит в памяти (что указывает на что и как). Ниже приведен код:

#include <stdio.h>
#include <stdlib.h>

void func(int **ptr)
{
    *ptr = (int *) malloc (sizeof(int));
    **ptr = 10;
    printf("Inside func: ptr: %p *ptr: %p **ptr: %p %d\n", ptr, *ptr, **ptr, **ptr);
}

void func2(int *ptr)
{
    int i = 10;
    ptr = (int *) malloc (sizeof(int));
    *ptr = 288;
    printf("Inside func2: ptr: %p *ptr: %p %d\n", ptr, *ptr, *ptr);
}

int main()
{
    int *a = NULL, *b = NULL;
    func(&a);
    printf("&a: %p, a: %p, *a: %p *a: %p %d\n", &a, a, *a, *a, *a);
    func2(b);
    printf("*b: %d\n", *b);
    return 0;
}

Вывод:

main.c:8:51: warning: format ‘%p’ expects argument of type ‘void *’, but argument 4 has type ‘int’ [-Wformat=]          
main.c:16:42: warning: format ‘%p’ expects argument of type ‘void *’, but argument 3 has type ‘int’ [-Wformat=]         
main.c:23:33: warning: format ‘%p’ expects argument of type ‘void *’, but argument 4 has type ‘int’ [-Wformat=]         
main.c:23:40: warning: format ‘%p’ expects argument of type ‘void *’, but argument 5 has type ‘int’ [-Wformat=]         
Inside func: ptr: 0x7ffcf5c49760 *ptr: 0x22f7010 **ptr: 0xa 10                                                          
&a: 0x7ffcf5c49760, a: 0x22f7010, *a: 0xa *a: 0xa 10                                                                    
Inside func2: ptr: 0x22f7030 *ptr: 0x120 288                                                                            
Segmentation fault (core dumped)

В шутку c -> когда a & ptr назначены и указывают на те же области памяти, почему это не может произойти на func2. В любом случае для * ptr я передаю b (который является адресом * b) и изменяю значение.

Невозможно понять, что указывает на что и как. Если кто-то может помочь, буду очень благодарен.

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

Ответы [ 4 ]

1 голос
/ 25 февраля 2020

Позвольте мне сказать это по-другому,

рассмотрим пример,

int x;
int *y = &x;
int **z = &y;
x = 10;

Что упрощает это,

enter image description here

Примечание : Только для иллюстрации я выбрал адрес x, y, z в качестве 0x1000,0x2000,0x3000 соответственно.


Что происходит в func1?

ptr локально для func1, *ptr - это то же самое, что и доступ к a, а **ptr - это то же самое, что и доступ к динамически выделяемой памяти. Динамически распределенная память сохраняется до *ptr, т. Е. До a.

Что происходит в func2?

ptr локально для func2 и указывает на NULL при вызове функции func2(b). malloc, ptr будет удерживать динамически выделенную память, но не изменяет b. При выходе из func2 объем памяти просачивается (т. Е. Теряется указатель для освобождения памяти).

#include <stdio.h>
#include <stdlib.h>

void func(int **ptr)
{
    *ptr =  malloc (sizeof(int));
    **ptr = 10;
    printf("Inside func: ptr: %p *ptr: %p **ptr: %d\n", ptr, *ptr, **ptr);
}

void func2(int *ptr)
{
    int i = 10;
    ptr =  malloc (sizeof(int));
    *ptr = 288;
    printf("Inside func2: ptr: %p *ptr: %d\n", ptr, *ptr);
}

int main()
{
    int *a = NULL, *b = NULL;
    func(&a);
    printf("&a: %p, a: %p, *a: %d\n", &a, a, *a);
    func2(b);
    printf("b: %p\n", b);
    return 0;
}

вывод

Inside func: ptr: 0x7ffc75e14030 *ptr: 0x1db0010 **ptr: 10
&a: 0x7ffc75e14030, a: 0x1db0010, *a: 10
Inside func2: ptr: 0x1db0030 *ptr: 288
b: (nil)

Рассмотрим Я приведу результат mallo c? в ваш код.

1 голос
/ 25 февраля 2020

Может быть, это немного помогает:

int a=20, *pa=&a, **ppa=&pa;

var  mem       val
a   (0x1000)   20
pa  (0x2000)   0x1000
ppa (0x3000)   0x2000

ppa   == 0x2000
*ppa  == 0x1000
**ppa == 20

pa    == 0x1000
*pa   == 20
**pa  not possible

&a    == 0x1000
&pa   == 0x2000
&ppa  == 0x3000

Если вы звоните func2(pa), вы звоните func2(0x1000). Это место. Так что только переменчиво, а не па. Если вы звоните func(ppa), вы звоните func(0x2000). Это расположение ПА. Так что па и а изменчивы, а не ппа.

1 голос
/ 25 февраля 2020

Указатель b никогда не инициализировался, не в main и не в функции. Он не указывает ни на один допустимый блок памяти.

Вы можете попробовать следующее. & b - указатель на целое число.

int b = 0;

func2(&b);
0 голосов
/ 25 февраля 2020

Я пытаюсь дать вам быстрый ответ ...

объявление с одним указателем, например void func2(int *ptr), даст вам доступ к ячейке памяти любого значения int, на которое указывает ptr. но если вы используете void func(int **ptr), вы указываете адрес указателя на переменную int.

Вы используете func2(b); без предварительного назначения b (так как это указатель на int) действительного адреса, что-то как это:

int an_integer = 13;
int *b = &an_integer;
func2(b); // now it should work
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...