从汇编看c++中extern关键字的使用

2016-02-19 09:49 10 1 收藏

人生本是一个不断学习的过程,在这个过程中,图老师就是你们的好帮手,下面分享的从汇编看c++中extern关键字的使用懂设计的网友们快点来了解吧!

【 tulaoshi.com - 编程语言 】

在c++中,extern关键字用来声明变量和函数,在声明函数的时候,有和没有extern的效果一样,即下面两条语句具有同样的效果:
代码如下:

extern void fun();
void fun();

  但是对于变量,有和没有extern就有区别,当有extern时,只是告知编译器存在这个变量,编译器并不为该变量分配存储空间,即真正的声明;若没有extern,则在声明的同时,编译器也为该变量分配存储空间。

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/)

下面是有extern的情形时的c++源码:
代码如下:

int main() {
    extern int i;
}

下面是对应的汇编码:
代码如下:

; 1    : int main() {

    push    ebp
    mov    ebp, esp;esp为指向栈顶的一个寄存器,始终指向栈顶 ebp也是一个寄存器,用来在给main函数分配的栈空间上寻访局部变量,因此常常作为基址
                ;上面两句的作用是将前一个栈的基址保存(压栈),然后让ebp指向当前函数的栈空间,再次作为基址

; 2    :     extern int i;
; 3    : }

    xor    eax, eax
    pop    ebp
    ret    0;这三句是用来退栈用,以及函数的返回

从上面的汇编码可以看出,并没有为变量i在站上分配任何存储空间

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/)

下面是没有extern的情形的c++源码:
代码如下:

int main() {
    int i;
}

下面是对应的汇编码:
代码如下:

; 1    : int main() {

    push    ebp
    mov    ebp, esp
    push    ecx;与有extern时的最大的不同就是这一句
               ;ecx也是一个寄存器,这里讲ecx的值压栈,等同于为变量i在栈上分配了存储空间
               ;由于ecx中的值不确定,因此,如果我们访问没有初始化的局部变量,常常得到一个奇怪的值

; 2    :     int i;
; 3    : }

    xor    eax, eax
    mov    esp, ebp
    pop    ebp
    ret    0

可以看出,没有extern关键字时,确实为变量i在栈上分配了存储空间

上面的汇编使用cl指令在命令行产生的,如果用vs2010来产生汇编码,汇编码可能不一样,但意思是一样的。

来源:https://www.tulaoshi.com/n/20160219/1592250.html

延伸阅读
c++中,如果没有为一个类提供析构函数,那么编译器会为这个类提供默认的析构的函数。由于析构函数的功能和构造函数相反,因此和默认的构造函数类似,编译器也会提供无用的默认的析构函数,和非无用的析构函数。两者的分析情况一样(对于默认的构造函数分析,请参看《从汇编看c++中默认构造函数的使用分析》)。并且编译器会提供非无用的默认析构...
1.引言 C++语言的创建初衷是“a better C”,但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同。 !-- frame contents -- !-- /frame contents -- 作为一种欲与C兼容的语言,C++保留了一部分过程式语言的特点(被世人称为“不彻底地面向对象”),因而它可以定义不属于任何类的...
C99中新增加了restrict修饰的指针: 由restrict修饰的指针是最初唯一对指针所指向的对象进行存取的方法, 仅当第二个指针基于第一个时,才能对对象进行存取。 对对象的存取都限定于基于由restrict修饰的指针表达式中。 由restrict修饰的指针主要用于函数形参,或指向由malloc()分配的内存空间。 restrict数据类型不改变程序的语义。 编译器...
C# 中的 关键字 之:base、this。base 关键字用于从派生类中访问基类的成员:调用基类上已被其他方法重写的方法。 指定创建派生类实例时应调用的基类构造函数。 基类访问只能在构造函数、实例方法或实例属性访问器中进行。 示例: 在派生类中调用基类方法。 以下是引用片段: // base 关键字 ...
JScript的语法教程里面说在声明变量时忽略var要害字是完全合法的。但是事实经常又证实想当然的结果是不可靠的。 看看下面这几个例子的结果就知道问题了: script language="javascript" var var00 = 0; document.write(var00 + 'br');var var01 = 1; function foo() { document...

经验教程

969

收藏

77
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部