#C/C++程序运行流程(main函数前后做了什么?)
[TOC]
##原由
今天有人问一个c程序编译出错的问题,代码太长,就不贴了。大概是这样子的。
#include
#include
char buf[100];
strcpy(buf,"hello world");
int mian()
{
printf(buf);
return 0;
}
他的代码中的操作也类似,就是对一个全局数据进行了一次strcpy初始化,但是编译报错了。
##错误原因
其实这个错误是很简单的,只要弄清楚C程序的运行流程就可以了。 这里的strcpy被谁调用了呢?显然是没有的。因为C程序的入口点是main函数,如果把初始化过程放在main函数里面就没问题了。
这里出现的问题是没搞清楚声明或定义与执行操作的语句的区别。
声明或定义是可以全局的但是执行某些操作的语句只能在某个函数内进行。
来一个更简单的例子,这样可能会更明白。
#include
int a;
a=3;
int mian()
{
printf("a=%d\n",a);
return 0;
}
现在编译一下,看看效果
gcc a.c
a.c:8:1: warning: data definition has no type or storage class
a=3;
^
虽然没有报错,但是有一个警告警告:数据定义没有类型或存储类。这说明了这里的两个a就不是同一个。 编译器把第一个int a;和a=3看做了一个声明和一个定义,如果把a=3放入到main函数中,警告就会消失。
这里还不够明显,稍加修改一下,再看就更明显了
#include
#include
int a;
b=5;
int main()
{
printf("a = %d b = %d\n",a,b);
return 0;
}
编译运行一下,看这次的报错就明白了吧。
o@o-pc:~/test$ gcc a.c
a.c:8:1: warning: data definition has no type or storage class
b=5;
^
o@o-pc:~/test$ ./a.out
a = 0 b = 5
##说说C/C++程序的运行流程
这里只是简单的说一下。 1、全局变量/对象的构建,初始化。对于全局变量,没有给定初始化值的,初始化为0。对于全局对象,没有指定构造函数的,调用默认构造函数。 2、进入main函数
main函数中的语句执行,函数调用 3、退出main函数 4、全局变量对象的回收。
我们可以写一个程序来验证一下,看看这个程序的输出结果与上面说的是否一致。
#include
class A{
public:
A(){puts("默认构造");};
A(int a){printf("带参构造 %d\n",a);};
~A(){puts("析构");}
};
A a1;
A a2(2);
int c;
int d=5;
int main()
{
printf("c = %d, d = %d\n",c,d);
return 0;
puts("sssssss");
}
编译运行
zo@o-pc:~/test$ g++ a.cpp
o@o-pc:~/test$ ./a.out
默认构造
带参构造 2
c = 0, d = 5
析构
析构
o@o-pc:~/test$
可以看出,程序的运行结果与前面所说一致。 先是全局变量/对象的构建,默认初始化值和构造函数调用都正确了。 然后是main函数的调用。 最后是在main函数结束后再去调用全局对象的析构。(因为没有输出ssssssss,所以说明return后main函数就结束(退栈)了,任何函数return了,就是该函数的调用结束了) 看来确实如此了。