C указатели на функции - PullRequest
       1

C указатели на функции

0 голосов
/ 05 января 2012

В моем приложении c у меня есть следующая декларация:

typedef double mat[MAX_SIZE][MAX_SIZE];

У меня также есть глобальная переменная:

mat aaa;

в функции я хочу сделать следующее:

void func2(mat ccc)
{
   ccc = aaa;
}

void func1()
{
    mat bbb;
    func2(bbb);
    bbb[1][2] = 3;
}

Я хочу, чтобы операции после func2(), которые я выполняю на bbb, влияли на глобальную переменную aaa, но они этого не делают.

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

Ответы [ 4 ]

1 голос
/ 05 января 2012

Вам нужно сделать bbb указатель и отправить по адресу bbb.

void func1()
{
    mat *bbb;
    func2(&bbb);
    (*bbb)[1][2] = 3;
}

И отредактируйте func2 примерно так:

void func2(mat **ccc){
    *ccc=&aaa;
}
0 голосов
/ 05 января 2012

В этом коде есть концептуальная ошибка - выражение массива не может быть целью назначения. Если вы пытались написать

void func1(void)
{
   mat bbb;
   bbb = aaa; 
   bbb[1][2] = 3;
}

компилятор выдаст диагностику для выражения bbb = aaa (gcc дает диагностику "несовместимые типы в присваивании", поскольку aaa преобразуется в тип указателя; подробнее об этом ниже). То, что вы пытаетесь сделать, передав bbb в func2, фактически одно и то же, и в конечном итоге не сработает.

Давайте избавимся от typedefs, чтобы мы могли видеть действительные типы

double aaa[MAX_SIZE][MAX_SIZE];
...
void func2(double (*ccc)[MAX_SIZE])
{
   ccc = aaa;
}

void func1()
{
  double bbb[MAX_SIZE][MAX_SIZE];
  func2(bbb);
  bbb[1][2] = 3;
}

Если это не операнд операторов sizeof или унарных & или строковый литерал, используемый для инициализации другого массива в объявлении, выражение типа "массив N-элементов из T" будет быть заменено выражением типа «указатель на T», значением которого является адрес первого элемента массива. Когда вы вызываете func2, выражение bbb преобразуется из типа "MAX_SIZE массив из MAX_SIZE массив из double" в "указатель на MAX_SIZE массив из double"; следовательно, объявление ccc как double (*ccc)[MAX_SIZE].

Аналогично, в строке ccc = aaa в func2 выражение aaa преобразуется из типа double [MAX_SIZE][MAX_SIZE] в double (*)[MAX_SIZE].

Пока что func2 является кошерным, потому что ccc является выражением-указателем, а не выражением массива, поэтому присваивание разрешено. ccc также оказывается совершенно отличным от bbb (получает копию значения указателя, которое оценивается bbb), поэтому запись в ccc не влияет на bbb. Если вы попытались обойти это, передав указатель на bbb, например:

void func2(double (*ccc)[MAX_SIZE][MAX_SIZE])
{
  *ccc = aaa;
}

void func1(void)
{
  double bbb[MAX_SIZE][MAX_SIZE];
  func2(&bbb);
  bbb[1][2] = 3;
}

компилятор выдаст диагностику на *ccc = aaa, либо потому, что *ccc имеет тип массива, либо потому что типы *ccc и aaa несовместимы (помните, aaa преобразуется в указатель выражение).

0 голосов
/ 05 января 2012

Вы имеете в виду, bbb[1][2] = 3; будет сделано на aaa? Тогда вам придется сделать так:

mat aaa;

mat* func2() {
    return &aaa;
}
void func1() {
    mat* bbb = func2();
    (*bbb)[1][2] = 3;
}
0 голосов
/ 05 января 2012

Ваш тип mat не тип указателя, это массив.Вы не можете назначать переменные массива в C. Обычный способ решить вашу проблему - использовать указатели:

void func1(void)
{
  mat *bbb = &aaa;
  (*bbb)[1][2] = 3;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...