例1,函数中的字符数组
- 当前例子中,func函数中定义了一个字符数组,它的创建位置在栈区,因此当func函数返回后该字符数组就被销毁了,因此以下方式主函数中不能成功打印出字符串。
点击查看代码
#include<stdio.h>
char * func(){
char a[] = "hello world";
return a;
}
int main(){
char *p = func();
printf("%p\n", p);
printf("%s\n", p);
return 0;
}
例2,函数中的字符串常量
- 例2相比例1只改变了一小点,即字符数组换成了一个字符指针指向一个字符串常量的首地址,字符串常量在常量区,因此函数返回后依然存在,因此在主函数中可以直接打印。
点击查看代码
char * func(){
char *a = "hello world";
return a;
}
int main(){
char *p = func();
printf("%p\n", p);
printf("%s\n", p);
return 0;
}
相同的字符串常量在常量区只有一份
- 字符串常量的本质就是存储在常量区的字符数组,但是为了节省内存,同样的字符串常量在常量区只会存储一份。
- 比如下边这个例子中,两次把同一个字符串常量给一个指针,打印出来的p对应的地址是相同的。
![]()
![]()
总结
- 上边两个例子中的字符数组a[]和字符指针a在函数返回后都被销毁了,并且它们都成功得将地址传了出去,区别在于第一个例子中字符串是存在栈区的,第二个例子中字符串是存在常量区的。
- 所谓的地址传递和值传递本质上都是值传递,只不过地址传递时候传递的值是地址。
- 而char a[] 这里a不仅仅是个地址,还是个数组名,因此它有了两重含义,第一重含义就是当前字符串的首地址,第二重含义决定了它是一个局部数组变量,存储在栈区。
- char *a这里的a则就是个指针,是一个局部指针变量,该变量的值是字符串的首地址,但是由于它没有第二重含义,因此不负责字符串的存储问题,因此这里的字符串是存在常量区的。当然,该字符串不能修改。