Ⅰ 编译器编译高级语言为低级语言的时候,给全局变量或静态变量是如何分配内存的
对于C和C++的编译器,全局变量和静态变量都是在专门的数据区保存的,更具体一点,一般是在.data和.bss段保存的,具体在哪个段,编译器会根据代码中是否对这些变量进行了初始化来决定,如果初始化过,并且初始化的值不为0,那么这个这个变量一般就会被放在编译结果的.data段中,否则就是放在.bss段中。
.data段中就保存变量的符号,还保存变量的初始化值,而在.bss段中,只保存变量的符号,而不保存值,这是因为这部分的变量都将被初始化为0,这也是为什么static声明的变量即使没有初始化也会是0的原因。
这些段都会在程序被执行的时候由操作系统(或链接器)加载到指定的内存中,便完成相应的初始化。
Ⅱ c语言问题。关于变量内存分配
变量由编译器分配空间
变量的地址不是连续分配的是因为内存对齐
C99规定int、unsigned int和bool可以作为位域类型,但编译器几乎都对此作了扩展,允许其它类型类型的存在。
使用位域的主要目的是压缩存储,其大致规则为:
1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;
2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++采取压缩方式;
4) 如果位域字段之间穿插着非位域字段,则不进行压缩;
Ⅲ 全局变量在编译时怎么分配空间
如果不需要使用就不要定义全局变量,因为只要定义了,代码又参与编译就会分配内存,局部变量定义了编译程序还帮着分析变量有无被使用并提示未被使用的变量,而全局变量则不会被分析是否有被使用,所以要小心使用,少做无谓的浪费,
全局变量能占用的总空间数是有限的,超过限度时编译器会提示且拒绝链接,不能生成最终执行文件
Ⅳ c++编译系统在编译时对静态存储变量分配存储单元吗
是啊,就是在编译的时候分配的么,不过你也可以动态分配,比如malloc函数,这样的内存是在堆中申请的,所以程序执行的时候才会申请,一般的变量什么的,包括数组都是在栈中存放,堆就是要靠用户管理的数据区域,栈则是有系统自动管理的。
Ⅳ c编译器将变量分配在 什么存储器
DEV C++TurboC2.0Visual studio 6.0Code::Blocks以上几款编辑器都可以在64位系统中运用。按照步骤如下:以Code::Blocks为例1首先下载下载Codeblocks这个软件,目前最新版本是13.12,2这个软件是英文的,所以软件是英文界面,建议读者使用英文版,不要去使用汉化版本,毕竟C语言是外国人开发的,所以用英文的界面会比较适合以后的能力提供,这个界面直接点击【I Agree】,进如下一步安装3这个是选择安装模式的界面,一般你的电脑是一个账户的,不是多人使用的电脑,所以这里选择Full就行了,就是给电脑所有用户安装4来到这个界面选择安装路径,这里强烈建议修改下安装路径,不建议使用默认的路径,默认的路径中【Program Files】中有一个空格,以后安装一个插件可能会出问题,所以建议自己建立一个文件作为该软件的安装路径,比如这里是在D盘建立了一个Develop的文件夹,作为开发软件的安装路径,然后安装路径就选择了D:\Develop\CodeBlocks,这里可以根据自己实际情况定义。5安装结束之后,弹出提示是否运行Code::Blocks,这里都可以选,选择运行6Code::Blocks的启动界面,这里是13.12版本,在上述经验有说到7这个直接选择Set as default就行了,因为此时你还没有安装其他的插件,所以其他的选项是灰色的,然后点击OK8紧接着看到的就是软件的这界面,这个界面就是Code::Blocks的界面
Ⅵ C语言的变量根据分配的存储空间的不同 可以分为哪三种变量
C语言变量存储类型
auto
static
extern
static extern
register
auto 局部变量
auto 变量是用堆栈(stack)方式占用储存器空间,因此,当执行此区段是,系统会立即为这个变量分配存储器空间,而程序执行完后,这个堆栈立即被系统收回.在大括号{}内声明.
自动变量就是指在函数内部定义使用的变量。他只是允许在定义他的函数内部使用它。在函数外的其他任何地方都不能使用的变量。自动变量是局部变量,即它的区域性是在定义他的函数内部有效。当然这说明自动变量也没有链接性,因为它也不允许其他的文件访问他。由于自动变量在定义他的函数的外面的任何地方都是不可见的,所以允许我们在这个函数外的其他地方或者是其他的函数内部定义同名的变量,他们之间不会发生冲突的。因为他们都有自己的区域性,而且它没有链接性(即:不允许其他的文件访问他的)。来看看自动量的持续性。计算机在执行这个函数的时候,创建并为它分配内存,当函数执行完毕返回后,自动变量就会被销毁。这个过程是通过一个堆栈的机制来实现的。为自动变量分配内存就压栈,而函数返回时就退栈。
static 静态变量
一、局部静态变量
局部变量按照存储形式可分为三种auto, static, register。
与auto类型(普通)局部变量相比, static局部变量有三点不同:
1. 存储空间分配不同
auto类型分配在栈上, 属于动态存储类别, 占动态存储区空间, 函数调用结束后自动释放, 而static分配在静态存储区, 在程序整个运行期间都不释放. 两者之间的作用域相同, 但生存期不同.
2. static局部变量在所处模块在初次运行时进行初始化工作, 且只操作一次。
3. 对于局部静态变量, 如果不赋初值, 编译期会自动赋初值0或空字符, 而auto类型的初值是不确定的.
特点: static局部变量的”记忆性”与生存期的”全局性”
所谓”记忆性”是指在两次函数调用时, 在第二次调用进入时, 能保持第一次调用退出时的值.
注意事项:
1. “记忆性”, 程序运行很重要的一点就是可重复性, 而static变量的”记忆性”破坏了这种可重复性, 造成不同时刻至运行的结果可能不同.
2. “生存期”全局性和唯一性. 普通的local变量的存储空间分配在stack上, 因此每次调用函数时, 分配的空间都可能不一样, 而static具有全局唯一性的特点, 每次调用时, 都指向同一块内存, 这就造成一个很重要的问题 ---- 不可重入性!!!
二、外部静态变量/函数
在C中static有了第二种含义:用来表示不能被其它文件访问的全局变量和函数。, 但为了限制全局变量/函数的作用域, 函数或变量前加static使得函数成为静态函数。但此处“static”的含义不是指存储方式,而是指对函数的作用域仅局限于本文件(所以又称内部函数)。注意此时, 对于外部(全局)变量, 不论是否有static限制, 它的存储区域都是在静态存储区, 生存期都是全局的. 此时的static只是起作用域限制作用, 限定作用域在本模块(文件)内部.
使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名。
extern 变量
外部变量 定义在程序外部,所有的函数很程序段都可以使用.
外部变量可能会在某一程序段被重新定义,以段内变量为参考值.
static extern 变量
静态外部变量和外部变量差别在于,外部变量生命可以同时给多个文件使用,而静态外部变量则只能给声明此变量的文件使用.
register 变量
寄存器变量,是由寄存器分配空间,访问速度比访问内存快,加快执行速度.寄存器大小有限.
在c语言当中可以使用寄存器变量来优化程序的性能,最常见的是在一个函数体当中,将一个常用的变量声明为寄存器变量: register int ra; 如果可能的话,编译器就会为它分配一个单独的寄存器,在整个函数执行期间对这个变量的操作全都是对这个寄存器进行操作,这时候就不用频繁地去访存了,自然就提高了性能。
不能用于全局变量。现在的情况是VC忽略用户定义的REGISTER,因此定义一个REGISTER变量与不定义一个REGISTER是一样的,编译器进行相同的优化,因为MS认为,REGISTER是系统中宝贵的资源,应该由系统统一调配,而且认为VC编译器的优化能力要大于一般的程序员。因此也有人说register关键字在PC机(x86CPU)无用,编译器按自动变量处理。
注意: register是不能取址的。
register int j; int *p = &j;是错的,因为无法对寄存器的寻址。
【摘自http://..com/link?url=-j__t2Ou7LNCgyoA8N06a】
Ⅶ c++中为什么有些变量在编译是就由编译器分配了内存空间,还没有运行怎么会占用内存呢
还没有运行怎么会占用内存呢?!(这一点还要怀疑吗!?)
所谓在编译期间分配空间指的是静态分配空间(相对于用new动态申请空间),如全局变量或静态变量(包括一些复杂类型的常量),它们所需要的空间大小可以明确计算出来,并且不会再改变,因此它们可以直接存放在可执行文件的特定的节里(而且包含初始化的值),程序运行时也是直接将这个节加载到特定的段中,不必在程序运行期间用额外的代码来产生这些变量。
其实在运行期间再看“变量”这个概念就不再具备编译期间那么多的属性了(诸如名称,类型,作用域,生存期等等),对应的只是一块内存(只有首址和大小),所以在运行期间动态申请的空间,是需要额外的代码维护,以确保不同变量不会混用内存。比如写new表示有一块内存已经被占用了,其它变量就不能再用它了; 写delete表示这块内存自由了,可以被其它变量使用了。(通常我们都是通过变量来使用内存的,就编码而言变量是给内存块起了个名字,用以区分彼此)
内存申请和释放时机很重要,过早会丢失数据,过迟会耗费内存。特定情况下编译器可以帮我们完成这项复杂的工作(增加额外的代码维护内存空间,实现申请和释放)。从这个意义上讲,局部自动变量也是由编译器负责分配空间的。进一步讲,内存管理用到了我们常常挂在嘴边的堆和栈这两种数据结构。
最后对于“编译器分配空间”这种不严谨的说法,你可以理解成编译期间它为你规划好了这些变量的内存使用方案,这个方案写到可执行文件里面了(该文件中包含若干并非出自你大脑衍生的代码),直到程序运行时才真正拿出来执行!
Ⅷ GCC编译器局部变量地址分配为什么总是从低
原因:GCC的堆栈保护技术—— canary的使用。
使用的原因是为了防止某些溢出的攻击。但是只是溢出时方向发生了改变,并没有起到太大的作用,可能对于传统的一些攻击方法有用。
GCC 中的堆栈保护实现
Stack Guard 是第一个使用 Canaries 探测的堆栈保护实现,它于 1997 年作为 GCC 的一个扩展发布。最初版本的 Stack Guard 使用 0x00000000 作为 canary word。尽管很多人建议把 Stack Guard 纳入 GCC,作为 GCC 的一部分来提供堆栈保护。但实际上,GCC 3.x 没有实现任何的堆栈保护。直到 GCC 4.1 堆栈保护才被加入,并且 GCC4.1 所采用的堆栈保护实现并非 Stack Guard,而是 Stack-smashing Protection(SSP,又称 ProPolice)。
SSP 在 Stack Guard 的基础上进行了改进和提高。它是由 IBM 的工程师 Hiroaki Rtoh 开发并维护的。与 Stack Guard 相比,SSP 保护函数返回地址的同时还保护了栈中的 EBP 等信息。此外,SSP 还有意将局部变量中的数组放在函数栈的高地址,而将其他变量放在低地址。这样就使得通过溢出一个数组来修改其他变量(比如一个函数指针)变得更为困难。
Ⅸ 编译器在编译的时候做了什么给申明的变量分配内存
第一是将java文件编译成字节码文件
就是class文件
给jvm执行
第二就是分配常量池
就是给你代码里面的变量和方法分配空间
Ⅹ 我们经常看到书上面说的 某某变量的内存单元是编译器在编译时候分配的 是什么意思
所谓在编译期间分配空间指的是静态分配空间(相对于用new动态申请空间),如全局变量或静态变量(包括一些复杂类型的常量),它们所需要的空间大小可以
明确计算出来,并且不会再改变,因此它们可以直接存放在可执行文件的特定的节里(而且包含初始化的值),程序运行时也是直接将这个节加载到特定的段中,不
必在程序运行期间用额外的代码来产生这些变量。
其实在运行期间再看“变量”这个概念就不再具备编译期间那么多的属性了(诸如名称,类型,作用
域,生存期等等),对应的只是一块内存(只有首址和大小),
所以在运行期间动态申请的空间,是需要额外的代码维护,以确保不同变量不会混用内存。比如写new表示有一块内存已经被占用了,其它变量就不能再用它了;
写delete表示这块内存自由了,可以被其它变量使用了。(通常我们都是通过变量来使用内存的,就编码而言变量是给内存块起了个名字,用以区分彼此)
内存申请和释放时机很重要,过早会丢失数据,过迟会耗费内存。特定情况下编译器可以帮我们完成这项复杂的工作(增加额外的代码维护内存空间,实
现申请和释 放)。从这个意义上讲,局部自动变量也是由编译器负责分配空间的。进一步讲,内存管理用到了我们常常挂在嘴边的堆和栈这两种数据结构。
最后对于“编译器分配空间”这种不严谨的说法,你可以理解成编译期间它为你规划好了这些变量的内存使用方案,这个方案写到可执行文件里面了(该文件中包含若干并非出自你大脑衍生的代码),直到程序运行时才真正拿出来执行。