有这样一段代码:

view plaincopy

#include "stdio.h"

char *get_string_1()

{

char p[] = "hello world!";

return p;

}

char *get_string_2()

{

char *p = "hello world!";

return p;

}

int main()

{

char *p;

p = get_string_1();

printf("get_string_1:%s\n",p);

p = get_string_2();

printf("get_string_2:%s\n",p);

return 0;

}

输出:

get_string_1:(乱码或者没有输出,linux下没有任何输出)

get_string_2:hello world!

1.为什么输出结果是这样?

2.字符串"abc"是常量吗?

3.char *p = "abc";这样写到底合不合法,实际应用中能不能这样写?

解析:

char *p = "hello world!";与char p[] = "hello world!"; 两者都用来声明一个字符串,并将其初始化为hello world!,但是表示的意义确是大不相同。

从其声明的对象来说:

char p[] = "hello world!"; //用来声明一个数组p,数组大小为12字节。

char *p = "hello world!"; //用来声明一个指针p,指向“hello world!”字符串起始位置。

从存储位置来说:

char p[] = "hello world!"; //p数组作为局部变量被存储在栈区;

char *p = "hello world!"; //在这个声明中,"hello world!"被存储在静态数据区,而且是全局的,p仅仅就是个指针,指向这个区域。不信的话可以试试下边的代码,看是不是同一个地址:

char *p1 = "hello world!";

char *p2 = "hello world!";

printf("p1:%x/np2:%x/n",p1,p2);

第一个问题:为什么输出结果是这样?

由于C函数执行完之后对栈区进行清除操作,对静态数据区和堆则没有,因此get_string_1()函数执行完就释放了栈区内存,所以根本就不存在存有"hello world!"声明时的内存,也就不可能有所输出。

第二个问题:"abc"是常量吗?答案:有时是,有时不是

(1)不是常量的情况:

"abc"作为字符数组初始值的时候就不是,如

char str[] = "abc";

因为定义的是一个字符数组,所以就相当于定义了一些空间(注意!)来存放"abc",而又因为字符数组就是把字符一个一个地存放的,所以编译器把这个语句解析为

char str[3] = {'a','b','c'};

以字符串形式出现的,编译器都会为该字符串自动添加一个0作为结束符,所以char str[] = "abc";的最终结果是

char str[4] = {'a','b','c','\0'};

做一下扩展,如果char str[] = "abc";是在函数内部写的话,那么这里的"abc\0"因为不是常量,所以应该被放在栈上。

(2)是常量的情况:

把"abc"赋给一个字符指针变量时,如

char* ptr = "abc";

因为定义的是一个普通指针,并没有定义空间(注意!)来存放"abc",所以编译器得帮我们找地方来放"abc",显然,把这里的"abc"当成常量并把它放到程序的常量区是编译器最合适的选择。所以尽管ptr的类型不是const char*,并且ptr[0] = 'x';也能编译通过,但是执行ptr[0] = 'x';就会发生运行时异常,因为这个语句试图去修改程序常量区中的东西。

第三个问题,char *p = "hello world!";这样写到底合不合法?

记得哪本书中曾经说过char* ptr = "abc";这种写法原来在c++标准中是不允许的,但是因为这种写法在c中实在是太多了,为了兼容c,不允许也得允许。虽然允许,但是建议的写法应该是 const char* ptr = "abc";这样如果后面写ptr[0] = 'x'的话编译器就不会让它编译通过,也就避免了上面说的运行时异常。

再扩展一下:

1.如果char* ptr = "abc";写在函数体内,那么虽然这里的"abc\0"被放在常量区中,但是ptr本身只是一个普通的指针变量,所以ptr是被放在栈上的,只不过是它所指向的东西被放 在常量区罢了。

2.字符串常量的类型可以理解为相应字符常量数组的类型,如"abcdef"的类型就可以看成是const char[7] 。

3.如果真的需要使用"abcd"作为指针,建议写为const char * p="abcd";

4.如果是初始化字符串数组,建议写为char p[]="abcd";

5.如果p为指针,需要初始化,应该是char *p;p=malloc(STR_SIZE);strcpy(p,"abcd");

char *p=abc 与 char p[]=abc 的区别相关推荐

  1. char *c = abc和char c[]=abc

    转自:http://blog.csdn.net/wallwind/article/details/7210474 char *c = "abc"和char c[]="ab ...

  2. char* str = abc ;跟char str[] = abc;的区别

    突然发现了一个以前一直默认的错误,同样char *c = "abc"和char c[]="abc",前者改变其内容程序是会崩溃的,而后者完全正确. 程序演示: ...

  3. 面试题--字符串指针与字符串数组的区别char* st=abc;与char* str[]=abc;的异同

    题1.   删除串中指定的字符(做此题时,千万不要开辟新空间,否则面试官可能认为你不适合做嵌入式开发) 参考代码: void delChar(char* str, char c) { int i, j ...

  4. java char 打印_Java中char[]输出不是内存地址的原因详解

    前言 Java中共有八种基本数据类型:byte,int,short,long,float,double,char,boolean. 计算机中的基础数据单位是bit, 1byte=8bit. 数据类型 ...

  5. C++中 char* 、string、 char、char[]在各种情况下的输入与输出

    之前在自己练手写代码的时候总是会在字符串,字符这一块卡住,今天写下这篇文章给自己长长记性! 其实在代码过程中会遇到很多很玄学的问题.刚刚在尝试的时候找到了之前写的测试字符串的程序,放到另外一个工程里跑 ...

  6. c语言char数组和short数组的区别,详解C语言中Char型指针数组与字符数组的区别

    详解C语言中Char型指针数组与字符数组的区别 详解C语言中Char型指针数组与字符数组的区别 1.char 类型的指针数组:每个元素都指向一个字符串,指向可以改变 char *name[3] = { ...

  7. String a = “abc“ 和 new String(“abc“)的区别

    String a = "abc":String b = "abc": JVM会使用常量池来管理字符串直接量.在执行这句话时,JVM会先检查常量池中是否已经存有& ...

  8. 报错笔记:cannot convert parameter 1 from 'char [1024]' to 'unsigned char *'

    第一段:数组的类型是char,因此函数在引用const char 型的指针的时候,必须用char类型数组的首地址.如果是byte类型的指针的首地址,则会报cannot convert paramete ...

  9. 深入理解const char*p,char const*p,char *const p,const char **p,char const**p,char *const*p,char**const

    原文网址:http://www.cnblogs.com/rushuizhijing/archive/2011/08/26/2154737.html 深入理解const char*p,char cons ...

最新文章

  1. ubuntu 安装ImageMagic
  2. Training—Managing Audio Playback
  3. linux学习笔记:1.基础知识和命令行基本操作
  4. centos7 安装rabbitMQ3.6.6
  5. 相对完善的Java通过JDBC操纵mysql的例子
  6. 算法:递归-八皇后问题(回溯算法)
  7. Controller @Autowired注解 无法注入值为null的问题
  8. activeperl安装不成功_SWOOLE进阶-00环境安装
  9. 华人运通高合HiPhiX维修手册电路图技术培训用户手册资料
  10. CAD图纸转BMP格式图片时怎么设置输出色彩?
  11. 计算机无法 鼠标没反应,鼠标插电脑上没反应怎么回事_鼠标连接电脑没反应的解决步骤...
  12. Vmware虚拟机设置固定IP地址
  13. Vue el-upload插件上传批量文件
  14. python绘制包络线_包络线和包络谱计算程序
  15. 学会这招,远离年金险99%的坑
  16. 第147杆147分诞生!吉尔伯特冠军联赛创历史
  17. 云桌面与桌面云,到底有什么区别?
  18. J2SE-Java基础
  19. android 手机扔起来的高度,三防AGM X2评测:吴京硬汉本色扔海里也不怕
  20. Prometheus 服务发现

热门文章

  1. EMNLP 2022投稿要求
  2. 《海错图笔记》的笔记 |【介部】
  3. 如果你因为这个辞职,下一份工作也不会好
  4. com.google.protobuf.ServiceException: java.lang.NoClassDefFoundError: com/yammer/metrics/core/Gauge
  5. 火线精英服务器维护要多长时间,火线精英游戏退款过程 绝对实用不取巧
  6. Semi-Supervised Semantic Image Segmentation with Self-correcting Networks基于自校正网络的半监督图像语义分割
  7. Module not found: Error: Can‘t resolve
  8. Android辅助功能实现自动抢红包
  9. Java面向对象三大特征:封装、继承、多态
  10. CoCosCreator2.2.1 入门教程