字符串数组和字符串指针
标签:c/c++
一个例子:
char *getStr(){ char str[] = "hello world"; // 生成在栈空间的局部变量 return str; }
有问题,因为 char str[] = "hello world";
定义了一个局部字符数组(注意str是数组),保存在栈中,初始化的字符串也在栈中,函数返回的时候,会释放栈中被调用函数对应的空间,返回该临时变量的地址,返回的是一个已经释放了的空间的地址。
解决方法:str[]改成*str即可,此时,str是在栈中,但是字符串常量是在.rodata段(常量区),释放的时候只会释放栈中的数组名,.rodata段数据的生命周期是整个函数的执行周期。
数组名的常量特性以及二维数组的初始化方法
char a[] = "hello"; a[0] = 'H'; // success a = "world"; // error
以上这样的代码会报错,因为数组只能被初始化相当于
char *const a = "hello"
,注意a是数组名,是一个地址常量;如果重新用一个字符串常量赋值,就会改变其指向的地址。也就是说 a 指向的地址不能改变,但 a 的内容可以改变可以用a[0]=’H’来改变a数组的值;,也可以用strcpy/memcpy进行赋值,只是对不变的地址进行内容填充。常量特性在自增方面的限制:
指针可以自增(void指针除外,因为类型未知,自增长度未知),但是数组a不能自增,常量不可以自增。下面是数组名常量特性的一个例子:
char a[3][5]; a = {"asas", "dds", "as"}; // error
【注意】是会报错的,就是因为“常量的原因”。所以二维数组的初始化方法:
声明的时候初始化
声明之后,赋值初始化,比如a[0][1] = ‘a’, 不能
a[0-3] = "asas"
,这种初始化方法使用的是字符串常量,赋值的时候会改变指针指向的地址,即会改变a的地址信息,不仅仅是二维的地址信息,还有二维下一维的地址也具有常量特性。strcpy/memcpy
等对a[0-3]进行初始化
指向字符串常量的指针的一个问题
- 版本 A
char *s = "hello";
- 版本 B
char *s; s = "hello"; // valid s[0] = 'H'; // invalid
虽然两个版本的赋值看起来都是用字符串常量进行赋值,但是版本 A 的那个语句叫做初始化,版本 B 才是赋值。跟A中字符串赋值不同的是:
”hello”中的双引号做了3件事:
1.申请了空间(在常量区),存放了字符串,不像数组存在栈中
2. 在字符串尾加上了’/0’
3.返回地址
所以,s是一个指针,指针指向地址很正常。s[0] = ‘H’;出错的原因是字符串保存在常量区!不能修改!