[英]What are the benefits of making a variable permanently a pointer as opposed to only using it as a pointer when needed in C?
I was looking through code as reference to a project I am currently working on.我正在查看代码作为我目前正在从事的项目的参考。 I noticed that instead of having a variable and then only casting a pointer to it temporarily to pass it as a parameter, it was just set to always be a pointer type.我注意到,不是有一个变量,然后只是临时转换一个指向它的指针以将其作为参数传递,而是将它设置为始终为指针类型。 (The line where it says Sprite* createSprite
) (上面写着Sprite* createSprite
的那一行)
Sprite* createSprite(Sprite* model, int x, int y) {
Sprite* self = malloc(sizeof(Sprite));
initSprite(model, self, x, y);
return self;
}
What I assume this is doing, is making the variable permanently a pointer.我假设这样做是使变量永久成为指针。
Instead of only using the pointer when I would need it:而不是只在需要时使用指针:
int a;
someFunction(&a); // We can still use a, and we can also pass it to someFunction as a pointer
This code is permanently casting the sprite object to a pointer:此代码将 sprite 对象永久转换为指针:
int *a;
someFunction(a); // While we can still use a, it will never be a normal variable.
Why would people want to do this and what are the benefits of it?人们为什么要这样做,这样做有什么好处?
In your first example在你的第一个例子中
int a;
someFunction(&a);
'a' exists on the stack , so it has a name you can use and take the address or etc. 'a' 存在于堆栈中,因此它有一个您可以使用并获取地址等的名称。
The sprite example精灵示例
Sprite* createSprite(Sprite* model, int x, int y) {
Sprite* self = malloc(sizeof(Sprite));
initSprite(model, self, x, y);
return self;
}
is almost certainly dynamically allocating its data on the heap.几乎可以肯定是在堆上动态分配其数据。 The only way you can refer to dynamically allocated memory is via a pointer您可以引用动态分配的内存的唯一方法是通过指针
Suppose you will need several sprites in your program.假设您的程序中需要几个精灵。 You could do something like你可以做类似的事情
Sprite s1;
initSprite(model, &s1, x, y);
Sprite s2;
initSprite(model, &s2, x, y);
Sprite s3;
initSprite(model, &s3, x, y);
And then later, if you needed a few more, you could do it the same way:稍后,如果你需要更多,你可以用同样的方式来做:
Sprite s4;
initSprite(model, &s4, x, y);
Sprite s5;
initSprite(model, &s5, x, y);
Sooner or later, though, this gets tedious and unworkable, so you want dynamic memory allocation .但是,迟早这会变得乏味且不可行,因此您需要动态内存分配。 That's what the createSprite
function is doing.这就是createSprite
函数正在做的事情。 Key within it is that call其中的关键是那个电话
Sprite* self = malloc(sizeof(Sprite));
which dynamically allocates memory for one more sprite.它为另外一个精灵动态分配内存。 That way, your program can have as many sprites in it as you want, quite likely a number that won't be known until runtime, once the user has started doing things.这样,您的程序可以在其中包含任意数量的精灵,很可能是一个直到运行时才知道的数字,一旦用户开始做某事。 But dynamically allocated memory always ends up involving pointers.但是动态分配的内存总是最终涉及指针。 It can't use static variable names like your int a
or my Sprite s1
, because by definition, there can only ever be a fixed, static number of those (that is, the number you picked the day you wrote the program).它不能使用像你的int a
或我的Sprite s1
这样的静态变量名,因为根据定义,它们只能有一个固定的、静态的数字(即你在编写程序的那天选择的数字)。
For comparison, it may be instructive to look at three other ways the createSprite
function could have been written, without using dynamic memory allocation.为了比较,看看createSprite
函数的其他三种编写方式可能会有所启发,而无需使用动态内存分配。
Sprite* createSprite2(Sprite* model, int x, int y) {
Sprite self;
initSprite(model, &self, x, y);
return &self;
}
This creates a local variable of type Sprite
(not pointer-to- Sprite
), but it doesn't work, at all.这会创建一个Sprite
类型的局部变量(不是指向Sprite
的指针),但它根本不起作用。 That local variable disappears when createSprite2
returns, so the pointer to it is immediately invalid.当createSprite2
返回时,该局部变量消失了,因此指向它的指针立即无效。
Sprite* createSprite3(Sprite* model, int x, int y) {
static Sprite self;
initSprite(model, &self, x, y);
return &self;
}
Here we make the local Sprint
variable static
, so it doesn't disappear when the createSprite3
returns.这里我们将本地Sprint
变量设置为static
,所以它不会在createSprite3
返回时消失。 But this doesn't work, either, because now there's really only one Sprite
object, shared by all the callers who have ever called createSprite3
, which is almost certainly not what was wanted, and won't work.但这也不起作用,因为现在实际上只有一个Sprite
对象,由所有调用过createSprite3
的调用者共享,这几乎肯定不是想要的,也不会起作用。
But there's one more possibility, which actually would work:但是还有另一种可能性,它实际上会起作用:
Sprite createSprite4(Sprite* model, int x, int y) {
Sprite self;
initSprite(model, &self, x, y);
return self;
}
Notice that this createSprite4
does not return a pointer -- it returns an actual instance of Sprite
.请注意,此createSprite4
不返回指针——它返回Sprite
的实际实例。 So the caller might look like所以来电者可能看起来像
Sprite s1 = createSprite4(model, x, y);
or或者
Sprite manysprites[10];
for(int i = 0; i < 10; i++)
manysprites[i] = createSprite4(model, x, y);
As I said, this could work fine, and is a bit of a counterargument to my assertion that "dynamically allocated memory always ends up involving pointers".正如我所说,这可以正常工作,并且有点反驳我的断言“动态分配的内存总是最终涉及指针”。 (Technically, though, there's still no dynamically allocated memory here, as we can see from the source code that there are exactly 1, or 10, Sprites allocated.) (但从技术上讲,这里仍然没有动态分配的内存,正如我们从源代码中看到的那样,恰好分配了 1 或 10 个 Sprite。)
createSprite
returns a pointer to self
; createSprite
返回一个指向self
的指针; if it was like this (which is what I guess you expected to also work):如果是这样(我猜你也希望这样):
Sprite* createSprite(Sprite* model, int x, int y) {
Sprite self;
initSprite(model, &self, x, y);
return &self;
}
the memory allocated to self
would be invalid by the time the function execution ended;到函数执行结束时,分配给self
的内存将无效; trying to access it through the returned pointer would most likely result in a segfault.尝试通过返回的指针访问它很可能会导致段错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.