我知道声明一个ststic变量并以这种方式初始化它static int *st_ptr = malloc(sizeof(int));
会产生一个编译错误消息(类型初始值设定项元素不是常量(,并且通过以这种方式使用单独的语句来解决此问题static int *st_ptr;
st_ptr = malloc(5*sizeof(int));
在这种情况下,我需要了解初始化运算符和赋值运算符之间的区别,以及为什么这种方式解决了这个问题?
首先,让我们简要介绍一下initialization
与 assignment
.
- 初始化:
这用于指定对象的初始值。通常,这意味着只有在定义变量时才会进行初始化。用于初始化对象的值称为发起器。从C11
,第6.7.9
章,
初始值设定项指定存储在对象中的初始值。
- 分配:
赋值是在任何(有效(给定的执行时间点分配(或设置(变量的值。引用标准,第6.5.16
章,
赋值运算符将值存储在由左操作数指定的对象中。
在简单分配的情况下(=
运算符(,
在简单赋值 (
=
( 中,右操作数的值被转换为 赋值表达式并替换存储在左侧指定的对象中的值 操作数。
也就是说,我认为您的查询与static
对象的初始化有关。
对于第一种情况,
static int *st_ptr = malloc(sizeof(int));
引自C11
标准文件第§6.7.9
章,初始化,第4段,
具有静态或线程存储持续时间的对象的初始值设定项中的所有表达式 应为常量表达式或字符串文字。
关于常量表达式,来自同一文档的第 6.6 章,(强调我的(
常量表达式不得包含赋值、递增、递减、函数调用、 或逗号运算符,除非它们包含在不是 评价。
显然,malloc(sizeof(int));
不是一个常量表达式,因此我们不能使用它来初始化 static
对象。
对于第二种情况,
static int *st_ptr;
st_ptr = malloc(5*sizeof(int));
您没有初始化static
对象。你让它不被理解。下一条指令,您将为其分配 malloc()
的返回值。因此,您的编译器不会产生任何抱怨。
当一个变量在函数中被声明为静态时,它是在"数据段"或"BSS段"中创建的,这取决于它是否被初始化。
此变量是在二进制文件中创建的,并且必须具有常量值 - 请记住 - 函数中的静态变量是在程序运行时甚至在main((启动之前创建的, 它不能用任何函数初始化,因为程序还没有"运行"(没有计算或函数调用(,
所以初始值设定项必须是常量,或者首先不初始化。
static int *st_ptr = malloc(sizeof(int));
在这里,您将st_ptr的创建与 malloc 绑定,但由于 malloc 是一个需要运行的函数,并且必须在任何其他函数运行之前创建st_ptr - 这会产生不可能的状态
static int *st_ptr;
st_ptr = malloc(5*sizeof(int));
在这里,st_ptr被创建并且未初始化,它的创建不绑定到任何函数。每次函数运行时 - malloc 都会发生。因此,不依赖于 malloc 的激活和创建st_ptr。
但正如我在评论中所说 - 这是极其危险的做法。 在同一变量上分配越来越多的内存。 避免它的唯一方法是在每个函数的末尾free(st_ptr)
。 这就是说 - 你不需要它首先是静态
粗略地说,C 中的初始化是编译器将二进制数据输出到可执行文件;赋值是由实际可执行代码执行的操作。
因此,static int i = 5
使编译器将数据字5
输出到可执行文件的数据部分;而int i = func()
使编译器生成多个CPU指令,call
调用子例程和mov
来存储结果。
因此,表达式static int i = func()
要求 1( 早于 main()
计算(因为这是初始化(,2( 一段要执行的用户代码(这可能仅在新程序实例的上下文中有意义(。可以通过创建一些在main()
之前执行的隐藏初始化子例程来解决这个问题。实际上,C++
这样做。但是C
没有这样的功能,所以静态变量只能用常量初始化。