我有这个很小的代码:
#include <stdio.h>
#include <stdlib.h>
typedef struct Ship Ship;
struct Ship
{
int x, y;
};
int main()
{
Ship* ship;
assignShip(ship);
printf("%d", ship->x);
return 0;
}
void assignShip(Ship* ship)
{
Ship anotherShip;
anotherShip.x = 10;
ship = &anotherShip;
}
它不起作用。 我创建一个名为ship的Ship类型的指针,然后我将指针传递给我的函数,我将指针设置为anotherShip,然后尝试查看它是否有效,但控制台进入“没有响应”并崩溃。 我做错了什么?
答案 0 :(得分:1)
“我做错了什么?”
一堆东西。
首先,在函数assignShip
内部,局部变量anotherShip
在函数末尾超出范围,使ship
指向不再存在的变量。
其次,由于您是按值而不是引用传递变量ship
,因此您无法在函数内对其进行永久更改。
相反:
#include <stdio.h>
#include <stdlib.h>
typedef struct Ship Ship;
struct Ship
{
int x, y;
};
int main()
{
Ship* ship = NULL;
assignShip(&ship);
// Check ship here, it is now non-NULL.
printf("%d", ship->x);
return 0;
}
void assignShip(Ship** ship)
{
static Ship anotherShip;
anotherShip.x = 10;
*ship = &anotherShip;
}
答案 1 :(得分:1)
您的代码和方法存在一些问题:
在C
中,参数按值传递。这意味着assignShip
会收到main中指针的副本。因此,此赋值ship = &anotherShip;
对main的Ship* ship;
变量没有影响,因为您修改了函数的本地副本。
对此的修复是指向主变量的指针。即:
int main()
{
Ship* ship;
assignShip(&ship); // we pass a pointer to the variable `ship`
printf("%d", ship->x);
return 0;
}
void assignShip(Ship** ship) // receive pointer to pointer
{
Ship anotherShip;
anotherShip.x = 10;
*ship = &anotherShip; // ... still wrong
}
然而,这将我们带到您的下一个重大问题:
anotherShip
是函数assignShip
的本地,这意味着一旦函数调用结束该变量被销毁,所以在main中你将留下一个悬空指针
对此的修复是使用动态分配:
int main()
{
Ship* ship;
assignShip(&ship);
printf("%d", ship->x);
return 0;
}
void assignShip(Ship** ship) // receive pointer to pointer
{
Ship* anotherShip = malloc(sizeof(Ship));
anotherShip->x = 10;
*ship = anotherShip;
}
现在我们有一个对象将在assignShip
的调用后继续存在。
这就把我们带到了下一个问题:
与自动存储持续时间不同,编译器负责管理对象的生命周期,动态存储持续时间是程序员的责任。因此,分配有malloc
的每个内存都必须与free
一起发布:
int main()
{
Ship* ship;
assignShip(&ship);
printf("%d", ship->x);
free(ship); // free the memory
return 0;
}
这将我们带到下一期:
虽然我们程序的上述版本在技术上是正确的,但我们处理内存管理的方式存在问题。
请考虑以下代码段:
Ship* ship;
assignShip(&ship); // we pass a pointer to the variable `ship`
assignShip
是否为参数分配内存。我们是否必须在它之后调用free
或者它是否期望接收指向有效内存位置的指针?
要回答这个问题,我们必须参考assignShip
(如果存在)和/或assignShip
一种方法是从函数名称中明确说明。例如allocateAndAssignShip
。
另一个是将分配移出函数:
int main()
{
Ship* ship = malloc(sizeof(Ship));
assignShip(ship);
printf("%d", ship->x);
free(ship);
return 0;
}
void assignShip(Ship* ship)
{
ship->x = 10;
}
答案 2 :(得分:0)
发货另一艘船;在堆栈中声明,一旦你离开函数指针未声明,这意味着你分配了未声明的指针。 要么分配它,要么在本地静态或全局,它应该工作