Как я могу исправить проблему с указателем в моем коде C? - PullRequest
0 голосов
/ 25 апреля 2020
#include <stdio.h>
void test(void **arg) {
    int foo = 3;
    **(int **)arg = foo; // I want to just fix this line!!
}

int main(void) {
    int temp = 0;
    printf("%d\n", temp);

    test((void **)&temp);

    printf("%d\n", temp);

    return 0;
}

В моем коде есть проблема 'Ошибка сегментации', но я не знаю, как я могу исправить свой код ..

Я хочу исправить только **(int **)arg = foo; line.

Кто-нибудь может мне помочь?

Ответы [ 3 ]

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

Похоже, вы пишете по адресу 0.

Потому что:

&temp - это указатель на int.

*((int**)&temp) - это int.

**((int**)&temp) используйте ваше значение из temp в качестве адреса.

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

В вашем коде функция test(void **temp), переменная temp является указателем на указатель, или двойным указателем. То есть это значение является адресом. Но когда вы вызываете test из main, это значение равно 0, что означает, что адрес является адресом 0.

Нельзя присвоить значение адресу 0.

0 голосов
/ 25 апреля 2020

Ваша функция

void test(void **arg);

ожидает «указатель на указатель на void» , то есть адрес местоположения, который содержит другой адрес, указывающий на общие c данные.

Когда вы вызываете функцию, вы не передаете то, что она ожидает

int temp = 0;
test((void **)&temp);

Фактически &temp - это адрес, указывающий на целое число. Но он ожидает адрес по адресу! Таким образом, когда внутри функции вы обращаетесь к ней дважды (каждая ссылка с помощью операторов * означает «разрешение» одного адреса) во второй раз, когда вы пытаетесь получить доступ к адресу 0.

Чтобы исправить его, просто передайте test указатель на указатель:

int temp = 0;
int *tempAddr = &temp; //tempAddr points to temp

test((void **)&tempAddr); //The type of the address of tempAddr is 'int  **'

Вы на самом деле просили другое: вы явно просили исправить строку **((int **) arg) = foo;.

Это не так просто, так как вы в настоящее время получаете недопустимый указатель на указатель, и нет способа сделать его действительным, просто изменив эту строку. Чтобы разобраться с этим, вам нужно изменить интерфейс test(), как показано ниже:

#include <stdio.h>
void test(void *arg) { // changed 'void **' to 'void *'
    int foo = 3;
    *(int *)arg = foo; // only one level of dereferencing
}

int main(void) {
    int temp = 0;
    printf("%d\n", temp);

    test((void *)&temp); // cast to 'void *' instead of 'void **'

    printf("%d\n", temp);

    return 0;
}
...