码迷,mamicode.com
首页 > 编程语言 > 详细

C++变量与内存浅诉

时间:2020-10-06 19:54:36      阅读:32      评论:0      收藏:0      [点我收藏+]

标签:cto   字节   字符   public   空间   除了   word   全局   允许   

变量存储的四个区域 : 静态存储区,栈区,堆区,常量区。

  静态存储区 : 静态变量,全局变量等

  栈区 : 局部变量

  堆区 : 通过malloc/operator new等函数申请的空间。

  常量区 : 在函数中声明的数组并以指针形式接收。

字符串常量的几种放置方式 :

  i) 在函数中声明的字符数组。

1 void test(){
2     char ch1[100] = "aaaacccc";
3 }

    会被翻译成

 1 test():
 2   push rbp
 3   mov rbp, rsp
 4   movabs rax, 7161677110935904609
 5   mov edx, 0
 6   mov QWORD PTR [rbp-112], rax
 7   mov QWORD PTR [rbp-104], rdx
 8   mov QWORD PTR [rbp-96], 0
 9   mov QWORD PTR [rbp-88], 0
10   mov QWORD PTR [rbp-80], 0
11   mov QWORD PTR [rbp-72], 0
12   mov QWORD PTR [rbp-64], 0
13   mov QWORD PTR [rbp-56], 0
14   mov QWORD PTR [rbp-48], 0
15   mov QWORD PTR [rbp-40], 0
16   mov QWORD PTR [rbp-32], 0
17   mov QWORD PTR [rbp-24], 0
18   mov DWORD PTR [rbp-16], 0
19   nop
20   pop rbp
21   ret

 

    由此可见,内存被存放在栈中,并且 字符串数组内容 直接以指令的形式在运行时四字节四字节地移动到栈区中。

    由于这种实现方式,不宜以这种方式申请较大的 数组。 

    1) 可能会爆栈。

    2) 运行时复制数组,速度挺慢。

  ii) 在函数中声明字符指针并赋值。

    字符串会被放入到只读区,作为字符串常量,指针变量则在栈中,且不可以用指针变量修改字符串常量(因为是只读的)。

1 void test(){
2     char* ch1 = "aaaacccc";
3 }

    会被翻译成 :

1 .LC0:
2   .string "aaaacccc"
3 test():
4   push rbp
5   mov rbp, rsp
6   mov QWORD PTR [rbp-8], OFFSET FLAT:.LC0
7   nop
8   pop rbp
9   ret

    直接使用 label 声明字符串,在加载时,内存就已经复制好了。

    可以看到,这里只有一份 .LC0,如若利用 ch1 对数组进行修改,运行时会报错 : Segmentation fault (core dumped)

    这种方式适合只读的字符串,为了避免运行时报错,最好以 

    const char * ch1 = "aaaacccc";
    进行声明,如若之后修改代码,使用了 ch1 修改字符串,就会编译报错。
  iii) 在全局以两种形式声明数组
1 char * ch1 = "aaaacccc";
2 char ch2[9] = "aaaacccc";
3 void test(){
4     ch1[0] = c;
5     ch2[0] = c;
6 }

    会被翻译成 :

 1 .LC0:
 2   .string "aaaacccc"
 3 ch1:
 4   .quad .LC0
 5 ch2:
 6   .string "aaaacccc"
 7 test():
 8   push rbp
 9   mov rbp, rsp
10   mov rax, QWORD PTR ch1[rip]
11   mov BYTE PTR [rax], 99
12   mov BYTE PTR ch2[rip], 99
13   nop
14   pop rbp
15   ret

    可以看到 ch1除了字符串本身,还有一个八字节指针的内存空间 (第三四行, .quad是个汇编伪指令 gas的指令,用来定义一个quard word也就是4字(8字节))。

    而全局数组ch2则直接通过label+offset来进行访问和修改的。

  iiii) 在对象中声明字符数组和字符指针

    下面的代码运行时会出现段错误,原因和在函数中声明字符指针并通过其修改字符串常量一样,这样声明字符串会变为常量,存储在只读区内不允许修改。

 1 struct str{
 2 private :
 3     char* ch4 = "ch4";
 4     char ch5[4] = "ch5";
 5 public :
 6     str(){
 7         ch4[1] = 0; 
 8     }
 9 };
10 void test(){
11     str* s = new str();
12     str* s2 = new str();
13 }

    会被翻译成 :

 1 .LC0:
 2   .string "ch4"
 3 str::str() [base object constructor]:
 4   push rbp
 5   mov rbp, rsp
 6   mov QWORD PTR [rbp-8], rdi
 7   mov rax, QWORD PTR [rbp-8]
 8   mov QWORD PTR [rax], OFFSET FLAT:.LC0
 9   mov rax, QWORD PTR [rbp-8]
10   mov DWORD PTR [rax+8], 3500131
11   mov rax, QWORD PTR [rbp-8]
12   mov rax, QWORD PTR [rax]
13   add rax, 1
14   mov BYTE PTR [rax], 48
15   nop
16   pop rbp
17   ret
18 test():
19   push rbp
20   mov rbp, rsp
21   push rbx
22   sub rsp, 24
23   mov edi, 16
24   call operator new(unsigned long)
25   mov rbx, rax
26   mov rdi, rbx
27   call str::str() [complete object constructor]
28   mov QWORD PTR [rbp-24], rbx
29   mov edi, 16
30   call operator new(unsigned long)
31   mov rbx, rax
32   mov rdi, rbx
33   call str::str() [complete object constructor]
34   mov QWORD PTR [rbp-32], rbx
35   nop
36   mov rbx, QWORD PTR [rbp-8]
37   leave
38   ret

  有个有趣的现象,在类中直接赋初始值,但是翻译成汇编赋值操作被放入到了 构造函数 中。

C++变量与内存浅诉

标签:cto   字节   字符   public   空间   除了   word   全局   允许   

原文地址:https://www.cnblogs.com/vizdl/p/13763067.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!