gpt4 book ai didi

c - 返回指针时,什么时候数据需要是静态的?

转载 作者:行者123 更新时间:2023-11-30 19:01:36 25 4
gpt4 key购买 nike

我注意到我想对有关指针和变量的问题进行解答,这并不是真正的问题,但我想了解详细信息。简而言之,为了绕过使用全局变量,我已经开始让函数返回指向函数内部数据的指针。有时,该数据需要是静态的,而其他时候则不是。

例如,假设我有一个函数,该函数创建2d char数组,并在其中填充“ a”并返回指向该数组的指针。当调用者尝试使用该指针访问和修改2d数组所在的内存时,将出现随机数据,而不是2d数组的内容。我发现将2d数组声明为static可以解决此问题,因为该数组的内容保存在其作用域之外。

现在,另一方面,我有一个声明结构的函数,并使用值对其进行初始化。然后,该函数返回指向该struct变量的指针。尝试通过指针访问结构的值时,调用方应该具有无意义的数据,但有趣的是,没有。我认为就像在2d数组的情况下一样,在函数调用之后,由于struct不是静态的,因此应该释放该内存中的数据。但是,事实并非如此,尽管它不是静态的,但我可以通过指针访问所有结构的元素。

总体而言,在函数完成之后,只要该数据是静态的(在2d数组情况下),调用方就可以访问和修改在该函数中创建的变量的数据,但是有时变量的数据会保留在范围之外,即使不是标记为静态(结构用例)。为什么?

最佳答案

您对在charstruct的二维数组中出现的数据的观察在函数返回后是否持续存在,是偶然的结果,而不是C标准定义的行为,您可能不依赖它们。它们仅仅是C编译器在特定情况下的行为的产物。在其他情况下,它们可能会更改,并且可能无法依赖。

每当您提供要在函数返回后使用的对象时(例如通过返回指向该对象的指针),该对象都不得具有自动存储期限。它可以具有静态存储持续时间,分配的存储持续时间或线程存储持续时间。

首先,让我们澄清一些术语。这对于理解概念很重要。 C标准不使用术语“全局变量”。它通常不使用“变量”来描述对象,也根本不使用“全局”来描述对象。在C标准中,您认为变量是标识符和对象。标识符是对象的名称,而对象是可以表示值的数据存储区。

C标准是否保证某个对象可以在特定时间使用取决于对象的生存期。生存期是指在程序执行期间对象存在于C语言的计算模型中。生命周期部分取决于其存储持续时间。存储时间取决于定义或创建对象的方式和位置。

寿命还受对象标识符范围的影响。范围是在源代码中可见(可以使用)标识符的位置。范围和生存期之间存在关系,但是它们是截然不同的东西。

有四个存储期限(还有一个特殊的临时存储期限,我将不在这里讨论):


如果使用_Thread_local声明标识符,则其对象具有线程存储持续时间。它的生命周期从创建线程开始,到线程执行结束时结束。因此,只要函数的线程仍在执行,就可以在函数返回后使用它。
否则,如果使用staticextern或在函数参数的任何块或列表之外(实际上在任何函数之外)声明标识符,则其对象具有静态存储持续时间。它存在于整个程序执行过程中,因此在执行过程中可以随时使用。
否则,对于对象的任何标识符(而不是类型定义,函数等),其对象具有自动存储期限。它与在其中声明的语句块相关联。(一个块是括号内的一系列语句,{ ... }。这可以是定义函数或嵌套在其中的块的主要块。)其寿命在执行时结束关联的块末端。 C标准不能保证在块的执行结束后尝试使用自动对象时会发生什么。


请注意,当函数调用子例程时,该函数的执行(包括其中的块)会暂时挂起,但不会结束。 (当函数返回时,执行结束,或者调用了诸如abortexitlongjmp之类的特殊例程。)这意味着在执行子例程时该对象仍然存在。即使子例程中的源代码的作用域与调用函数的作用域不同,也是如此。

由于上述原因,声明您不能使用超出其范围的对象的语句是错误的。范围不是确定是否可以访问对象的决定因素。终生是。

对于第四个存储期限:


具有分配的存储持续时间的对象由malloccallocreallocaligned_alloc创建,并且没有名称(标识符)。分配的对象从分配的时间扩展到释放的时间。因此,如果函数分配了一个对象并返回指向该对象的指针,则该指针可用于访问该对象,直到释放该对象为止。

关于c - 返回指针时,什么时候数据需要是静态的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57565355/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com