[关闭]
@zsh-o 2018-07-16T23:53:14.000000Z 字数 2014 阅读 1184

C++内存分配——字符串常量

C++


今天写程序出现了错误,如下

  1. /*
  2. * 对一个句子进行反转,每个词不反转
  3. */
  4. #include <iostream>
  5. #include <stdio.h>
  6. #include <string.h>
  7. using namespace std;
  8. /*
  9. * 对一个字符串逆序
  10. */
  11. char* reverse_string(char* s, int size_s){
  12. char* r = new char[size_s];
  13. int i = 0;
  14. while(i < size_s){
  15. int j = size_s - 1 - i;
  16. r[i] = s[j];
  17. i++;
  18. }
  19. return r;
  20. }
  21. char* reverse_string_(char* s, int size_s){
  22. int i = 0;
  23. while(i < size_s/2){
  24. char a = s[i];
  25. int j = size_s - 1 - i;
  26. s[i] = s[j];
  27. s[j] = a;
  28. i++;
  29. }
  30. return s;
  31. }
  32. int main(){
  33. char* s = "abcdefg";
  34. printf("%s\n", reverse_string(s, strlen(s)));
  35. // printf("%s\n", reverse_string_(s, strlen(s))); // s定义在栈区无法赋值
  36. char* ss = new char[100];
  37. for(int i=0; i<=strlen(s); i++){ //把'\0'复制过去
  38. ss[i] = s[i];
  39. }
  40. printf("%s\n", reverse_string_(ss, strlen(ss)));
  41. }

printf("%s\n", reverse_string_(s, strlen(s)));出现了运行时错误,s是字符串常量,被分配在了静态的常量区,再如下

  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <string.h>
  4. using namespace std;
  5. int main(){
  6. char* s1 = "abcdefg";
  7. char* s2 = "abcdefg";
  8. char a1[] = "abcdefg";
  9. char a2[] = "abcdefg";
  10. const char ca1[] = "abcdefg";
  11. const char ca2[] = "abcdefg";
  12. const char* cs1 = "abcdefg";
  13. const char* cs2 = "abcdefg";
  14. printf("%d %d %d %d %d", s1==s2, a1==a2, ca1==ca2, cs1==cs2, s1==cs1);
  15. }
  1. 1 0 0 1 1

可以看出char *const char *均是字符串常量,其相同字符串指向同一个内存地址,无法赋值,而char []const char []是局部字符数组变量,拥有各自的内存地址空间,被分配在栈区(局部变量分配在栈区,变量声明周期结束(函数结束)会被自动释放),下面程序正常执行

  1. char* s = "abcdefg";
  2. printf("%s\n", reverse_string(s, strlen(s)));
  3. // printf("%s\n", reverse_string_(s, strlen(s))); // s定义在栈区无法赋值
  4. char a[] = "abcdefg";
  5. printf("%s\n", reverse_string(s, strlen(s)));
  6. printf("%s\n", reverse_string_(a, strlen(a)));

最后来看看局部变量的释放:

  1. #include <stdio.h>
  2. #include <string.h>
  3. char* fun(){
  4. char s[] = "abcdefg";
  5. printf("Fun: %p: %s --- %p \n", s, s, &s);
  6. return s;
  7. }
  8. char* nfun(){
  9. char *s = new char[100];
  10. s = "abcdefg";
  11. printf("NFun: %p: %s --- %p \n", s, s, &s);
  12. return s;
  13. }
  14. int main(){
  15. char* s = fun();
  16. printf("Main: %p: %s --- %p\n", s, s, &s);
  17. char* ns = nfun();
  18. printf("NMain: %p: %s --- %p \n", ns, ns, &ns);
  19. }
  1. Fun: 0062FED8: abcdefg --- 0062FED8
  2. Main: 00000000: (null) --- 0062FF0C
  3. NFun: 0041A039: abcdefg --- 0062FEDC
  4. NMain: 0041A039: abcdefg --- 0062FF08

其中%p s代表指针s指向的地址,%s s代表输出字符串,%p &s代表指针s本身的内存地址
这里可以看到在fun()函数里面s是一个局部字符数组变量,被分配在了该函数的栈区,当函数结束时该指针被释放,则该函数返回的地址为空,则main函数里面的s指向的地址为空(00000000)。而nfun()函数里面的snew分配在了堆区,被用户申请和释放,故函数结束时仍然存在

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注