@zsh-o
2018-07-16T15:53:14.000000Z
字数 2014
阅读 1352
C++
今天写程序出现了错误,如下
/** 对一个句子进行反转,每个词不反转*/#include <iostream>#include <stdio.h>#include <string.h>using namespace std;/** 对一个字符串逆序*/char* reverse_string(char* s, int size_s){char* r = new char[size_s];int i = 0;while(i < size_s){int j = size_s - 1 - i;r[i] = s[j];i++;}return r;}char* reverse_string_(char* s, int size_s){int i = 0;while(i < size_s/2){char a = s[i];int j = size_s - 1 - i;s[i] = s[j];s[j] = a;i++;}return s;}int main(){char* s = "abcdefg";printf("%s\n", reverse_string(s, strlen(s)));// printf("%s\n", reverse_string_(s, strlen(s))); // s定义在栈区无法赋值char* ss = new char[100];for(int i=0; i<=strlen(s); i++){ //把'\0'复制过去ss[i] = s[i];}printf("%s\n", reverse_string_(ss, strlen(ss)));}
printf("%s\n", reverse_string_(s, strlen(s)));出现了运行时错误,s是字符串常量,被分配在了静态的常量区,再如下
#include <iostream>#include <stdio.h>#include <string.h>using namespace std;int main(){char* s1 = "abcdefg";char* s2 = "abcdefg";char a1[] = "abcdefg";char a2[] = "abcdefg";const char ca1[] = "abcdefg";const char ca2[] = "abcdefg";const char* cs1 = "abcdefg";const char* cs2 = "abcdefg";printf("%d %d %d %d %d", s1==s2, a1==a2, ca1==ca2, cs1==cs2, s1==cs1);}
1 0 0 1 1
可以看出char *和const char *均是字符串常量,其相同字符串指向同一个内存地址,无法赋值,而char []和const char []是局部字符数组变量,拥有各自的内存地址空间,被分配在栈区(局部变量分配在栈区,变量声明周期结束(函数结束)会被自动释放),下面程序正常执行
char* s = "abcdefg";printf("%s\n", reverse_string(s, strlen(s)));// printf("%s\n", reverse_string_(s, strlen(s))); // s定义在栈区无法赋值char a[] = "abcdefg";printf("%s\n", reverse_string(s, strlen(s)));printf("%s\n", reverse_string_(a, strlen(a)));
最后来看看局部变量的释放:
#include <stdio.h>#include <string.h>char* fun(){char s[] = "abcdefg";printf("Fun: %p: %s --- %p \n", s, s, &s);return s;}char* nfun(){char *s = new char[100];s = "abcdefg";printf("NFun: %p: %s --- %p \n", s, s, &s);return s;}int main(){char* s = fun();printf("Main: %p: %s --- %p\n", s, s, &s);char* ns = nfun();printf("NMain: %p: %s --- %p \n", ns, ns, &ns);}
Fun: 0062FED8: abcdefg --- 0062FED8Main: 00000000: (null) --- 0062FF0CNFun: 0041A039: abcdefg --- 0062FEDCNMain: 0041A039: abcdefg --- 0062FF08
其中%p s代表指针s指向的地址,%s s代表输出字符串,%p &s代表指针s本身的内存地址
这里可以看到在fun()函数里面s是一个局部字符数组变量,被分配在了该函数的栈区,当函数结束时该指针被释放,则该函数返回的地址为空,则main函数里面的s指向的地址为空(00000000)。而nfun()函数里面的s用new分配在了堆区,被用户申请和释放,故函数结束时仍然存在