Передать по значению в C
Привет, следующий код переносим?
Я просто передаю указатель по значению, и я могу изменить его в вызывающей программе!
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 ответа
Вы всегда передаете указатель на указатель по значению, заставляя его казаться единым указателем, когда вы присваиваете его себе и когда передаете в функцию; это работает только потому, что вы указали указатель на себя.
Что вы делаете в основном это:
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)
Да, вы можете изменить то, на что указывает указатель, но вы можете сделать это только потому, что указатель на него указывает:
p = &p;
Чтобы ответить на ваш вопрос, да, это портативно; но нет, это вообще не очень хорошая идея.
Вы на самом деле играете с указателями на указатели. Вы по-прежнему передаете указатель по значению, и вы не обманываете компилятор при изменении значения вызывающего. То, что вы изменяете, это просто значение, на которое указывает указатель на указатель.
Не очень хорошая идея для использования в реальной жизни, кроме того, чтобы запутать себя и других программистов.