解析char *p与char p[]
来源:互联网 发布:java 扫描二维码登陆 编辑:程序博客网 时间:2024/06/05 06:01
主要解析的问题:
问题1:
#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!
为什么会这样?
问题2:
char *p = "hello world!";这样写到底合不合法,实际应用中能不能这样写。
问题3:
char *p = "hello world!";与char p[]="hello world!";有什么细节和操作上的差异。
解析:
char *p = "hello world!";与char p[] = "hello world!"; 两者都用来声明一个字符串,并将其初始化为hello world!,但是表示的意义确是大不相同。
从其声明的对象来说:
char p[] = "hello world!";用来声明一个数组p,数组大小为12字节(这里如果用strlen函数为12,若用sizeof为13,因为'\0'的存在)。
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!"声明时的内存,也就不可能有所输出。
那么,写成char *p = "hello world!";到底合不合法呢?能不能这样写呢?
这是一个历史问题,在const关键字被引入C语言之前,这样写是合法的,而且存在了很长的一段时间,大量的代码在此期间运用了这种写法,新版C语言为了兼容,故允许这样写,但最好不要这样,因为这种写法终会被淘汰,说不定哪天你的代码用了新版的编译器,然后莫名的出了问题,要找这个BUG估计不是一件容易的事。现在最好写成:
const char *p = "hello world!";
或者
char p[] = "hello world!";
那他们在操作和细节上有什么区别呢?
区别很多,由于本人才疏学浅,只总结出以下几点,忘有知者补充:
1. char *p = "hello world!"; 可以用p++操作,sizeof(p) = 8;
2.char p[]="hello world!"; sizeof(p) = 13;
-----------------------------
下面转自另外一个人的博文
#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!,但是表示的意义确是大不相同。
从其声明的对象来说:
从存储位置来说:
第一个问题:为什么输出结果是这样?
由于C函数执行完之后对栈区进行清除操作,对静态数据区和堆则没有,因此get_string_1()函数执行完就释放了栈区内存,所以根本就不存在存有"hello world!"声明时的内存,也就不可能有所输出。
(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"因为不是常量,所以应该被放在栈上。
把"abc"赋给一个字符指针变量时,如
char* ptr = "abc";
因为定义的是一个普通指针,并没有定义空间(注意!)来存放"abc",所以编译器得帮我们找地方来放"abc",显然,把这里的"abc"当成常量并把它放到程序的常量区是编译器最合适的选择。所以尽管ptr的类型不是const char*,并且ptr[0] = 'x';也能编译通过,但是执行ptr[0] = 'x';就会发生运行时异常,因为这个语句试图去修改程序常量区中的东西。
第三个问题,char *p = "hello world!";这样写到底合不合法?
再扩展一下:
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");
http://kmplayer.iteye.com/blog/565605
- 解析char *p与char p[]
- 解析char *p与char p[] 区别
- 解析char *p与char p[]
- 解析char *p与char p[]
- 解析char *p与char p[] 区别
- 解析char *p与char p[]
- 解析char *p与char p[]
- 解析char *p与char p[]
- 解析char *p与char p[]
- 解析char *p与char p[]
- 解析char *p与char p[]
- 解析char *p与char p[]
- 解析char *p与char p[] , char (*p)[]与char *p[]
- char (*p)[]与char *p[]
- char *p与char p[]
- char* p与char p[]
- char* p与char p[]的不同
- char *p 与char p[] 比较
- poj2115 C Looooops (欧几里德)
- BZOJ1853 [Scoi2010]幸运数字 容斥原理
- 利用VTK构造球形(表面)点云
- noip2009 hankson的趣味题 (扩展欧几里得求最大公约数,最小公倍数与最大公约数)
- 创建型模式总结:都是来帮助我们创建对象的!
- 解析char *p与char p[]
- CRM-Hibernate逆向工程
- MySQL Meta中的length字段 -- (3) length的推导举例
- iOS开发中的网络请求
- XML Drawable 与9-Patches
- First Bad Version(二分查找的应用)
- FragmentPagerAdapter默认加载2项,返回时为创建视图
- centos下rpm打包简单实例
- [LeetCode]Lowest Common Ancestor of a Binary Search Tree