передать по значению в C - PullRequest
       11

передать по значению в C

1 голос
/ 29 декабря 2010

Привет, является ли следующий код переносимым?

Я просто передаю указатель по значению и могу изменить в вызывающей программе!

void foo(void *p)
{
 void **pp = (void**)p;
 *pp = "hahaha";
}

int main(int argc,char **argv)
{
 void *p = NULL;
 p = &p;
 printf("%p\n",p);
 foo(p);
 printf("%s\n",(char *)p);     // hahaha
 printf("%p\n",p);


return 0;
}

Ответы [ 3 ]

4 голосов
/ 29 декабря 2010

Да, вы можете изменить то, на что указывает указатель, но вы можете сделать это только потому, что указатель указывает на сам :

p = &p;

Чтобы ответить на ваш вопросда, это портативно;но нет, это вообще не очень хорошая идея.

3 голосов
/ 29 декабря 2010

Вы всегда передаете указатель на указатель по значению, заставляя его казаться единым указателем, когда вы назначаете его себе и когда вы передаете его функции; это работает только потому, что вы указали указатель на себя.

То, что вы делаете, в основном так:

void foo(void **p)
{
    *p = "hahaha";
}

int main(int argc,char **argv)
{
    void *p = NULL;
    printf("%p\n", &p);
    foo(&p);
    printf("%s\n",(char *)p);     // hahaha
    printf("%p\n", p);
    return 0;
}

с некоторыми добавками и трюками. «Трюки с картами в темноте», я бы сказал, и определенно не очень хорошая идея, чтобы использовать настоящую программу.

Чтобы действительно ответить на вопрос: да, он должен быть переносимым, потому что стандарт гарантирует, что каждый указатель данных может быть без проблем приведен к void * и обратно (это то, что вы делаете в своем коде все время) :

Указатель на void может быть преобразован в или из указателя на любой незавершенный объект или объект тип. Указатель на любой неполный объект или тип объекта может быть преобразован в указатель на void и обратно снова; результат должен сравниться с исходным указателем.

(C99, §6.3.2.3.1)

2 голосов
/ 29 декабря 2010

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

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

...