作用域指变量的有效范围,一般分为全局和局部的,局部的一般是指定义在花括号{}之内的,函数内内嵌了至少一个作用域(一对花括号构成一个作用域),由于内嵌了很多作用域,所以这些变量因为定义在不同的作用域而生效范围不同,变量定义在函数体内且在函数体内嵌的作用域之外与定义在内嵌作用域之内有什么区别呢?
#include<stdio.h>
int main()
{
int sum = 0,i,id = 0;
for(i = 0;i<8;i++)
{
id = i;
sum += id;
}
return 0;
}
利用命令objdump命令反汇编,汇编代码如下:
Disassembly of section .text:
0000000000000000 <main>:
0: 55 push %rbp 备份%rbp寄存器
1: 48 89 e5 mov %rsp,%rbp %rbp指向栈顶%rsp
4: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%rbp) sum
b: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) id
12: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp) i
19: eb 10 jmp 2b <main+0x2b> 跳转到地址2b处执行
1b: 8b 45 f8 mov -0x8(%rbp),%eax id的值保存在寄存器%eax中
1e: 89 45 fc mov %eax,-0x4(%rbp) %eax的值赋值给i
21: 8b 45 fc mov -0x4(%rbp),%eax i的值赋给寄存器%eax
24: 01 45 f4 add %eax,-0xc(%rbp) sum += i;
27: 83 45 f8 01 addl $0x1,-0x8(%rbp) i++;
2b: 83 7d f8 07 cmpl $0x7,-0x8(%rbp) i与7比较
2f: 7e ea jle 1b <main+0x1b> 如果i<=7则跳转到1b处执行
31: b8 00 00 00 00 mov $0x0,%eax
36: c9 leaveq
37: c3 retq
上面的C代码稍作修改 id变量定义在函数内且在内嵌作用域内
#include<stdio.h>
int main()
{
int sum = 0,i;
for(i = 0;i<8;i++)
{
int id = 0;
id = i;
sum += id;
}
return 0;
}
汇编代码如下:
test1.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%rbp)
b: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp)
12: eb 17 jmp 2b <main+0x2b>
14: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
1b: 8b 45 f8 mov -0x8(%rbp),%eax
1e: 89 45 fc mov %eax,-0x4(%rbp)
21: 8b 45 fc mov -0x4(%rbp),%eax
24: 01 45 f4 add %eax,-0xc(%rbp)
27: 83 45 f8 01 addl $0x1,-0x8(%rbp)
2b: 83 7d f8 07 cmpl $0x7,-0x8(%rbp)
2f: 7e e3 jle 14 <main+0x14>
31: b8 00 00 00 00 mov $0x0,%eax
36: c9 leaveq
37: c3 retq
汇编代码与上面的对比发现,在循环处多了movl $0x0,-0x4(%rbp),即每次循环都要比修改之前的代码多了写存储器操作,所以性能要比修改之前差,所以在编码时最好定义在函数内而在内嵌作用域之外
如下给出了一段测试用的C代码,无任何作用仅用作解释变量作用域不同的区别。
C代码 id变量定义在函数内且在内嵌作用域外#include<stdio.h>
int main()
{
int sum = 0,i,id = 0;
for(i = 0;i<8;i++)
{
id = i;
sum += id;
}
return 0;
}
利用命令objdump命令反汇编,汇编代码如下:
Disassembly of section .text:
0000000000000000 <main>:
0: 55 push %rbp 备份%rbp寄存器
1: 48 89 e5 mov %rsp,%rbp %rbp指向栈顶%rsp
4: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%rbp) sum
b: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) id
12: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp) i
19: eb 10 jmp 2b <main+0x2b> 跳转到地址2b处执行
1b: 8b 45 f8 mov -0x8(%rbp),%eax id的值保存在寄存器%eax中
1e: 89 45 fc mov %eax,-0x4(%rbp) %eax的值赋值给i
21: 8b 45 fc mov -0x4(%rbp),%eax i的值赋给寄存器%eax
24: 01 45 f4 add %eax,-0xc(%rbp) sum += i;
27: 83 45 f8 01 addl $0x1,-0x8(%rbp) i++;
2b: 83 7d f8 07 cmpl $0x7,-0x8(%rbp) i与7比较
2f: 7e ea jle 1b <main+0x1b> 如果i<=7则跳转到1b处执行
31: b8 00 00 00 00 mov $0x0,%eax
36: c9 leaveq
37: c3 retq
上面的C代码稍作修改 id变量定义在函数内且在内嵌作用域内
#include<stdio.h>
int main()
{
int sum = 0,i;
for(i = 0;i<8;i++)
{
int id = 0;
id = i;
sum += id;
}
return 0;
}
汇编代码如下:
test1.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%rbp)
b: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp)
12: eb 17 jmp 2b <main+0x2b>
14: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
1b: 8b 45 f8 mov -0x8(%rbp),%eax
1e: 89 45 fc mov %eax,-0x4(%rbp)
21: 8b 45 fc mov -0x4(%rbp),%eax
24: 01 45 f4 add %eax,-0xc(%rbp)
27: 83 45 f8 01 addl $0x1,-0x8(%rbp)
2b: 83 7d f8 07 cmpl $0x7,-0x8(%rbp)
2f: 7e e3 jle 14 <main+0x14>
31: b8 00 00 00 00 mov $0x0,%eax
36: c9 leaveq
37: c3 retq
汇编代码与上面的对比发现,在循环处多了movl $0x0,-0x4(%rbp),即每次循环都要比修改之前的代码多了写存储器操作,所以性能要比修改之前差,所以在编码时最好定义在函数内而在内嵌作用域之外