C什么时候创建变量?

C什么时候创建变量?,c,debugging,variables,C,Debugging,Variables,我使用的是ubuntu 12.04和Qt Creator 2.4.1。默认情况下,它构建我的C代码GCC 我正在调试我的程序(Qt-Creator(使用GDB)),并且已经可以看到许多变量,这些变量将在程序的后续步骤中调用/创建。在程序开始时看到所有变量正常吗?换句话说,我是否因为调试选项(-g)而在程序的早期阶段看到变量?例如,我“步入”代码并在第一步停止,即int main() char[1000]mesg在第129行执行,但是,我已经可以看到它和它的内存地址了。或int tem\u ho

我使用的是ubuntu 12.04和Qt Creator 2.4.1。默认情况下,它构建我的C代码
GCC

我正在调试我的程序(
Qt-Creator(使用GDB)
),并且已经可以看到许多变量,这些变量将在程序的后续步骤中调用/创建。在程序开始时看到所有变量正常吗?换句话说,我是否因为调试选项(
-g
)而在程序的早期阶段看到变量?例如,我“步入”代码并在第一步停止,即
int main()


char[1000]mesg在第129行执行,但是,我已经可以看到它和它的内存地址了。或
int tem\u hopt\u dist=0在第230行,但我已经看到它的值为“3”

是的,这是正常的。调试器不理解该语言的所有作用域语义,并显示数据,就好像所有变量都是在其最终内存位置初始化的,即使它们超出了作用域


有些调试器比其他调试器好。这是一个常见的恼怒源,例如,如果您习惯于将单独的索引变量都称为
i
,而调试器不会区分它们。

是的,这是正常的。调试器不理解该语言的所有作用域语义,并显示数据,就好像所有变量都是在其最终内存位置初始化的,即使它们超出了作用域

有些调试器比其他调试器好。这是一个常见的恼怒源,例如,如果您习惯于将单独的索引变量都称为
i
,调试器不会区分它们。

带有“静态持续时间”的变量(与
static
关键字不同,尽管声明的变量
static
通常具有静态持续时间)在执行模型中,在调用
main
时,“创建”。具有“自动持续时间”的变量(“在堆栈上”,许多人都这么称呼它们)通过
malloc
分配的变量持续到显式
free
d(或通过
realloc
等减少空间)

上面的密钥外带不是“在此时创建”,而是“在此点创建”。编译器可以自由地更早地这样做,如果这样做更有效的话。对于块范围、自动持续时间变量,通常将它们全部合并到一个大的入口点堆栈分配中最便宜,编译器只需一次“减法”即可完成指令(“从堆栈指针中减去常量”),在大多数典型的现代机器上。释放空间要么完全免费(“从函数返回”即可),要么只需一条指令(“将常量添加到堆栈指针”)

C99的可变长度数组(“VLA”)使这一点有点复杂。VLA通常必须在每次输入其封闭块时分配,并在每次退出块时释放。同样,这通常相当便宜(从堆栈指针中减去一个以创建VLA,再加一个以销毁它),但很明显,每个块两条指令比每个块零条指令更昂贵。这也会稍微影响一些编译时优化

如果您曾经使用过非标准的
alloca
函数,这通常也是通过从堆栈指针进行减法来实现的,而且它可能不会很好地使用VLAs,因为这种减法倾向于假设编译器已经完成了自己的“从堆栈指针进行减法”恰好一次,就在函数本身开始之前。

具有“静态持续时间”的变量(与
static
关键字不同,尽管声明的
static
变量通常具有静态持续时间)在执行模型中由调用
main
的时间“创建”。具有“自动持续时间”(“许多人称之为堆栈上的持续时间”)是在输入其作用域时创建的。通过
malloc
分配的变量持续到显式
free
d(或通过
realloc
等减少空间)

上面的密钥外带不是“此时创建”,而是“此时创建”。编译器可以自由地更早地执行此操作,如果这更有效的话。对于块范围、自动持续时间变量,通常最便宜的方法是将它们全部合并到一个大的入口点堆栈分配中,编译器只需一次“减法”即可指令(“从堆栈指针中减去常数”),在大多数典型的现代机器上。释放空间要么是完全免费的(“从函数返回”即可),要么只需要一条指令(“将常数添加到堆栈指针”)

C99的可变长度数组(“VLA”)使这一点有点复杂。VLA通常必须在每次输入其封闭块时分配,并在每次退出块时释放。同样,这通常相当便宜(从堆栈指针中减去一个以创建VLA,再加一个以销毁它),但很明显,每个块两条指令比每个块零条指令更昂贵。这也会稍微影响一些编译时优化


如果您曾经使用过非标准的
alloca
函数,这通常也是通过从堆栈指针进行减法来实现的,而且它可能不会很好地使用VLAs,因为这种减法倾向于假设编译器已经完成了自己的“从堆栈指针进行减法”恰好一次,就在函数本身启动之前。

很多次,静态定义的变量被编译到数据“部分”因此,如果您在该例程/函数的范围内,那么它可能在该点可见。数据段中的任何静态内容都可以在该例程的入口分配。很多时候,静态定义的变量被编译到程序的数据“段”,因此如果您在该例程/f的范围内