1

我知道 C 中有三种类型的静态减法:

1:Constant - 常量静态变量,例如:static const int i = 5;

2:Changable - 只是一个普通的静态变量,例如:static int hi = 10;

这是我的问题

还有另一种形式的静态,它采用“代码”的形式。这是什么意思,你能给我举个例子吗?

谢谢!

编辑:静态/常量变量是否存储在堆栈/堆中?

4

5 回答 5

8

也许你在谈论一个静态函数

这是“静态”一词的特定用法,它与静态变量完全不同。

当您声明一个函数“静态”时,这意味着它不能从另一个源文件链接。它通常用于保持某些功能“私有”。

[编辑] 请注意,理论上,仍然可以使用指针从另一个源文件访问函数代码,但这不是访问函数的正常方式(当然也不是最简单的方式)。感谢 Eric Postpischil 指出这一点。

不幸的是,C 标准中使用同一个词“静态”来表示两种不同的东西,具体取决于用于函数或变量。

[编辑]:这是一个不同的问题,但无论如何:在静态变量的情况下,它们既不是在堆中也不是在堆栈中分配的。它们是静态的,这意味着它们被分配在静态空间中,由编译器在启动时直接分配。堆栈用于内部函数变量,堆用于 malloc()/free()。

于 2013-04-29T17:20:53.630 回答
4

这个链接应该回答你的问题。

然而值得注意的是,除非您对 C 编译过程有足够的了解,否则这将是值得怀疑的。

可以在这里找到 GCC 的一个很好的参考。

我相信你在问静态函数..所以..

静态函数

默认情况下,C 中的函数是extern,这意味着该函数可以在同一项目的任何其他文件中使用(当然还有相同的代码)。

如果您不喜欢这种情况,并且希望将函数限制在定义它的文件中,请将其设为static

于 2013-04-29T17:19:19.693 回答
1

该关键字static在 C 中以多种不同的方式使用。(有一个笑话说,任何新版本的 ISO C 标准都需要为 . 创造新的含义static。)

快速总结:static块作用域定义上的关键字给出了实体静态存储的持续时间;在文件范围内,定义已经具有静态存储持续时间,而是为它们提供内部链接。

一个对象可能有几个存储期中的任何一个。具有“自动”存储持续时间的对象仅在执行封闭块期间存在于运行时。在程序的整个执行过程中存在一个具有“静态”存储持续时间的对象。(还有“已分配”和 C11 中新增的“临时”存储持续时间,我不会涉及。)

标识符的任何定义也有一个“链接”,它可以是外部的、内部的或无。链接控制标识符是否可跨翻译单元使用(基本上是源文件,但#included 文件不是单独的翻译单元)。顾名思义,链接与链接器有关。您可以在两个不同的源文件中使用具有内部链接的相同标识符,它将引用两个不同的实体。但是如果一个标识符有外部链接,它应该只定义一次,并且可以在多个源文件中声明(通常用);extern所有这些声明都将引用同一个实体。

如果您在块范围内(即在函数体内)定义对象(变量),则默认情况下它具有自动存储持续时间(并且没有链接)。添加关键字static使其具有静态存储持续时间,因此它存在并在对函数的调用中保留其值。(它不会影响标识符的可见性)。

如果您在文件范围内(即在任何函数体之外)定义对象,则默认情况下它具有静态存储持续时间和外部链接。将关键字添加static到定义中不会影响其存储持续时间,但会将其链接从外部更改为内部,从而对其他翻译单元隐藏名称。函数没有存储期限(只要程序运行,它们的代码就存在),但static会以同样的方式影响它们的链接,将其从外部更改为内部。

(C99为static数组类型的函数参数添加了另一个含义,与其他用途无关。)

于 2013-04-29T19:16:53.970 回答
1

静态/常量变量是否存储在堆栈/堆中?

嗯,不,它们是“全球”空间的一部分。堆栈和堆用于“动态”内存分配,而不是静态!

于 2013-04-29T20:59:29.730 回答
1

我认为有必要澄清我们在谈论什么并尝试使用正确的措辞。

限定词与关键字const无关。static

从技术上讲,static关键字出现在声明中,通常是存储类说明符,但从 C99 开始,它也可以出现在数组声明符中,尽管这很不寻常。

当它是存储类说明符时,就像在您发布的声明中一样,它会影响标识符的链接(文件之间的可见性)和已识别对象的存储持续时间(生命周期),但不会影响标识符的范围

6.2.2 标识符的链接

[...] 在一个翻译单元中,具有内部链接的标识符的每个声明都表示相同的对象或函数。[...]

如果对象或函数的文件范围标识符的声明包含存储类说明符static,则该标识符具有内部链接。30)


static30) 函数声明只有在文件范围内才能包含存储类说明符;见 6.7.1。

因此,标识符只能在声明它的翻译单元(即预处理后的源文件)中看到,无论是对象还是函数(也许这就是您要查找的内容)。因此,您可以使用声明仅在一个文件中使用的“私有”函数。

static void foo(void)
{
    // ...
}

static关键字 it 也与函数说明符一起使用,inline它具有特定的链接语义:https ://stackoverflow.com/a/216546/1202636

显然,当我们不在文件范围内而是在更受限制的范围static内(函数内的声明)时,链接问题变得无关紧要,因为这样的标识符根本没有链接。

6.2.4 对象的存储期限

一个对象,其标识符被声明为 [...] 具有外部或内部链接或存储类说明符static,具有静态存储持续时间。它的生命周期是程序的整个执行过程,它的存储值只在程序启动之前初始化一次。

这仅适用于对象标识符,它会影响对象的生命周期,例如让变量在调用之间保留其值及其初始化。

(顺便说一句,这样的对象也是用默认值初始化的)

正如我所说,static关键字的用法不太常见:它可以在函数原型内的数组声明符中使用,以告诉编译器作为参数给出的数组至少包含n 个元素。这是标准中的(修改后的)示例:

void f(double a[static 3][5]);

a该声明指定在任何调用中对应的参数f必须是指向至少三个 5 个双精度数组中的第一个的非空指针,而其他数组则不是。

.

静态/常量变量是否存储在堆栈/堆中?

再次const强调,该属性与存储对象的位置无关。该标准没有说明那个地方,通常有一个专用区域,但这是一个不同且已经回答的问题:静态缓冲区分配在哪里?

于 2013-04-29T19:17:43.367 回答