主要是C程序中的第一个函数还是第一个可执行语句?如果存在全局变量int a=0;
?
我一直被告知主要是程序的起点。但是,在我看来,赋予某些值并且是可执行语句的全局变量呢?
答案 0 :(得分:10)
在程序执行之前,静态存储持续时间的全局变量和一般对象在概念上初始化。
C11(N1570)5.1.2 / 1 执行环境:
应初始化具有静态存储持续时间的所有对象(设置为 程序启动前的初始值。
给定托管环境,函数main
被指定为必需入口点,程序执行开始。它可能有以下两种形式之一:
int main(void)
int main(int argc, char* argv[])
其中参数的名称不需要与上面相同(这只是一种惯例)。
对于独立环境入口点是实现定义,这就是为什么有时在嵌入式设备的C实现中遇到void main()
或任何不同形式的原因。
C11(N1570)5.1.2.1/1独立环境:
在独立环境中(可能需要执行C程序) 没有操作系统任何好处的地方),名称和类型 在程序启动时调用的函数是实现定义的。
答案 1 :(得分:6)
main
不是该计划的起点。程序的起点是程序的入口点,在大多数情况下,对于C程序员来说是透明的。通常它由 _start 符号表示,并在用汇编语言编写的启动代码中定义或预编译到C运行时初始化库(如crt0.o
)中。它负责对您正在采用的内容进行低级初始化,例如将未初始化的静态变量初始化为零。完成后,它会调用预定义的符号main
,这是您知道的main
。
答案 2 :(得分:5)
但是在我看来,分配了一些值并且是可执行语句的全局变量呢
你的意见是错误的。
在全局上下文中,只有变量定义才能存在,并且显式初始化。所有可执行语句(即赋值)都必须驻留在函数内。
详细说明,在全球范围内,你不能有像
这样的陈述int globalVar;
globalVar = 0; //error, assignement statement should be inside a function
然而,上述内容在函数内部完全有效,如
int main()
{
int localVar;
localVar = 0; //assignment is valid here.
关于初始化,例如
int globalVar = 0;
初始化发生在main()
开始之前,因此本身并不是执行的一部分。
详细说明全局变量初始化的场景,引用C11
,第6.2章,
如果是声明标识符的声明符或类型说明符 出现在任何块或参数列表之外,标识符具有文件范围,其中 终止于翻译单元的末尾。
和 flie scope 变量,
如果 对象标识符的声明具有文件范围,没有存储类说明符, 它的联系是外在的。
和外部链接的对象,
在没有存储类说明符的情况下声明其标识符的对象
_Thread_local
,以及外部或内部链接或存储类 说明符static
,具有静态存储持续时间。它的一生就是整个执行 程序及其存储的值仅在程序启动之前初始化一次。
答案 3 :(得分:0)
在理论上,仅限C标准的计划中,它是。
在实践中,它通常涉及更多。
在Linux,AFAIK上,内核将链接的图像加载到保留的地址空间,并首先调用可执行映像指定的动态链接器(除非可执行文件是静态编译的,在这种情况下没有动态链接部分)。
动态链接器可以加载依赖库,例如C库。
这些库可能会注册自己的启动代码,您也可以(gcc
主要通过__attribute__((constructorr))
)注册。
(C ++尤其需要用户提供的init代码,您需要在具有构造函数的C ++全局变量上运行一些启动代码。)
然后链接器调用图像的入口点,默认为_start(链接器允许您选择不同的名称,如果要深入挖掘),默认情况下由{{1提供}} 图书馆。 C
通过调用_start
来继续初始化C库。
在任何情况下,简单的全局初始化(例如main
)应该被编译并链接到您的可执行文件中,然后由操作系统(而不是您的代码)一次性加载,作为加载过程映像的一部分这些变量不需要用户提供的初始化代码。
答案 4 :(得分:0)
如果使用turbo c watch,你会发现第一个全局声明,然后在编译时数据段(给全局和静态变量提供内存)的主启动执行初始化为0。 因此虽然无法进行赋值,但是在编译时进行声明。
答案 5 :(得分:0)
是的,当你声明一个变量内存在编译时分配给它时,除非你不使用堆段(分配内存到指针),即在运行时发生的动态分配。但是由于全局从RAM变量的数据段部分得到它的内存,所以在编译时分配内存。 希望这会有所帮助。