[转载]char * 和char []的区别---之第一篇
char * 和char []的区别---之第一篇
原文地址http://blog.csdn.net/yahohi/article/details/7427724
在C/C++中,指针和数组在很多地方可以互换使用,所以经常有一种错觉,感觉数组和指针两者是完全等价的,于是经常出现在定义char ch[] 时,一旦给ch赋值与ch开辟的地址空间不等长的空间时会出现打印为“烫”字的情况
实上数组和指针是有很大的区别的。
汇总自己查找的资料:
char[]是一个数组定义,char*是指针定义
先说说指针和数组的区别
(1)指针和数组的分配
数组是开辟一块连续的内存空间,数组本身的标识符(也就是通常所说的数组名)代表整个数组,可以使用sizeof来获得数组所占据内存空间的大小(注意,不是数组元素的个数,而是数组占据内存空间的大小,这是以字节为单位的)。举例如下:
#include <stdio.h>
int main(void)
{
char a[] = "hello";
int b[] = {1, 2, 3, 4, 5};
printf("a: %d\n", sizeof(a));
printf("b memory size: %d bytes\n", sizeof(b));
printf("b elements: %d\n", sizeof(b)/sizeof(int));
return 0;
}
数组a为字符型,后面的字符串实际上占据6个字节空间(注意最后有一个\0标识字符串的结束)。从后面sizeof(b)就可以看出如何获得数组占据的内存空间,如何获得数组的元素数目。至于int数据类型分配内存空间的多少,则是编译器相关的。gcc默认为int类型分配4个字节的内存空间。
char[]是一个数组定义,char*是指针定义
(2)空间的分配
这里又分为两种情况。
第一,如果是全局的和静态的
char *p = “hello”;
这是定义了一个指针,指向rodata section里面的“hello”,可以被编译器放到字符串池。在汇编里面的关键字为.ltorg。意思就是在字符串池里的字符串是可以共享的,这也是编译器优化的一个措施。
char a[] = “hello”;
这是定义了一个数组,分配在可写数据块,不会被放到字符串池。
第二,如果是局部的
char *p = “hello”;
这是定义了一个指针,指向rodata section里面的“hello”,可以被编译器放到字符串池。在汇编里面的关键字为.ltorg。意思就是在字符串池里的字符串是可以共享的,这也是编译器优化的一个措施。另外,在函数中可以返回它的地址,也就是说,指针是局部变量,但是它指向的内容是全局的。
char a[] = “hello”;
这是定义了一个数组,分配在堆栈上,初始化由编译器进行。(短的时候直接用指令填充,长的时候就从全局字符串表拷贝),不会被放到字符串池(同样如前,可能会从字符串池中拷贝过来)。注意不应该返回它的地址。
cout经研究得出以下结论:
1、对于数字指针如int *p=new int; 那么cout<<p只会输出这个指针的值,而不会输出这个指针指向的内容。
2、对于字符指针入char *p="sdf f";那么cout<<p就会输出指针指向的数据,即sdf f
============================================================================
如果还不是很理解,水木上也有高人对此进行解释:
这里的char ch[]="abc";
表示ch 是一个足以存放字符串初值和空字符'/0'的一维数组,可以更改数组中的字符,但是char本身是不可改变的常量。
char *pch = "abc";
那么pch 是一个指针,其初值指向一个字符串常量,之后它可以指向其他位置,但如果试图修改字符串的内容,结果将不确定。
______ ______ ______
ch: |abc\0 | pch: | ◎-----> |abc\0 |
______ ______ ______
char chArray[100];
chArray[i] 等价于 *(chArray+i)
和指针的不同在于 chArray不是变量 无法对之赋值
另 事实上 i[chArray] 也等价于 *(chArray+i)
因此,总结如下:
1. char[] p表示p是一个数组指针,相当于const pointer,不允许对该指针进行修改。但该指针所指向的数组内容,是分配在栈上面的,是可以修改的。
2. char * pp表示pp是一个可变指针,允许对其进行修改,即可以指向其他地方,如pp = p也是可以的。对于*pp = "abc";这样的情况,由于编译器优化,一般都会将abc存放在常量区域内,然后pp指针是局部变量,存放在栈中,因此,在函数返回中,允许返回该地址(实际上指向一个常量地址,字符串常量区);而,char[] p是局部变量,当函数结束,存在栈中的数组内容均被销毁,因此返回p地址是不允许的。
同时,从上面的例子可以看出,cout确实存在一些规律:
1、对于数字指针如int *p=new int; 那么cout<<p只会输出这个指针的值,而不会输出这个指针指向的内容。
2、对于字符指针入char *p="sdf f";那么cout<<p就会输出指针指向的数据,即sdf f
那么,像&(p+1),由于p+1指向的是一个地址,不是一个指针,无法进行取址操作。
&p[1] = &p + 1,这样取到的实际上是从p+1开始的字符串内容。
分析上面的程序:
*pp = "abc";
p[] = "abc";
*pp指向的是字符串中的第一个字符。
cout << pp; // 返回pp地址开始的字符串:abc
cout << p; // 返回p地址开始的字符串:abc
cout << *p; // 返回第一个字符:a
cout << *(p+1); // 返回第二个字符:b
cout << &p[1];// 返回从第二个字符开始的字符串:bc
[转载]char * 和char []的区别---之第一篇的更多相关文章
- 转载:eclipse 搭建SSH项目(第一篇)
第一篇:原文地址:http://blog.csdn.net/aaaaaaaa0705/article/details/6288431(虽然没有具体的例子,不过逻辑性强点,比较容易看懂) SSH框架是最 ...
- Zookeeper 入门第一篇
转载原文地址: ZooKeeper学习总结 第一篇:ZooKeeper快速入门 ZooKeeper学习总结 第二篇:ZooKeeper深入探讨 ZooKeeper学习第一期---Zookeeper简单 ...
- <转载>深入 理解char * ,char ** ,char a[ ] ,char *a[] 的区别
C语言中由于指针的灵活性,导致指针能代替数组使用,或者混合使用,这些导致了许多指针和数组的迷惑,因此,刻意再次深入探究了指针和数组这玩意儿,其他类型的数组比较简单,容易混淆的是字符数组和字符指针这两个 ...
- [转载]char * 和char []的区别---之第二篇
原文地址:http://blog.sina.com.cn/s/blog_74a4593801019keb.html main() { char *p="abc123ABC";//c ...
- C/C++中char* 与char []定义的区别
转载请注明来自souldak,微博:@evagle Question: 给你一个字符串例如abb输出它包含的字符的所有可能排列. 例如abb输出3个:abb,bab,bba Answer: 假设我们自 ...
- [转载]MySQL之char、varchar和text的设计
[转载]MySQL之char.varchar和text的设计 来源:https://www.cnblogs.com/billyxp/p/3548540.html 首先我们先普及一下常识: 1.char ...
- char* 和char[]的区别
以下内容均来自互联网,系笔者汇总并总结. 1. 问题介绍 问题引入:在实习过程中发现了一个以前一直默认的错误,同样char *c = "abc"和char c[]="ab ...
- char *s="string"和char s[]="string"的区别
char *s="string"的内容是不可以改的 void main() { char* pStr1 = "Hello!"; char pSt ...
- 深入 理解char * ,char ** ,char a[ ] ,char *a[] 的区别
转自:https://blog.csdn.net/liusicheng2008_liu/article/details/80412586 1 数组的本质 数组是多个元素的集合,在内存中分布在地址相连的 ...
随机推荐
- 查看软、硬raid信息的方法
软件raid:只能通过Linux系统本身来查看cat /proc/mdstat可以看到raid级别,状态等信息. 硬件raid:最佳的办法是通过已安装的raid厂商的管理工具来查看,有cmdline, ...
- 错记-checkbox radio
很多时候我想会用到浏览器默认的单选按钮或者复选框,比如说偷懒的时候或者心情不好的时候╮(╯﹏╰)╭, 在html结构里我想实现点击文字旁边的单选按钮就跟着选中或反之,像这样:
- php怎么删除文件
php怎么删除文件 删除文件很简单只要使用unlink(文件名)就可以了.
- java枚举类型使用笔记
1.values()方法返回枚举所有实例的一个数组,调用这个数组的length方法,可以得到这个枚举对象中实例的个数 2.枚举类的每个实例,其实都是static的,可以通过static方法直接调用,而 ...
- 做个伪IE浏览器?!【来自官网】
原文:docwiki.embarcadero.com/RADStudio/Seattle/en/Building_a_VCL_Forms_Web_Browser_Application 选择File ...
- 共享内存shared pool (6):追踪sql语句
构建实验数据 --使用NC50用户查询(会话1) SQL> conn NC50/NC50 Connected. SQL> create table emp as select * from ...
- STL之容器基本操作
容器类 STL Container Header Applications vector <vector> 直接访问任意元素,快速插入.删除尾部元素 deque <deque> ...
- [terry笔记]物化视图 materialized view基础学习
一.物化视图定义摘录: 物化视图是包括一个查询结果的数据库对像(由系统实现定期刷新数据),物化视图不是在使用时才读取,而是预先计算并保存表连接或聚集等耗时较多的操作结果,这样在查询时大大提高了 ...
- VC中实现GCC的2个比较常用的位运算函数
在GCC中内嵌了两个位运算的函数,但在VC中并没有这两个函数(有相似函数). //返回前导的0的个数. int __builtin_clz (unsigned int x) //返回后面的0个个数,和 ...
- 使用VMDepot镜像快速部署CKAN开放数据门户
最新发布的CKAN VMDepot镜像针对中国用户强化了中文支持,提升了与MS Office办公软件的互操作性,并集成了常用插件和最佳实践配置参数. 使得CKAN原本十分复杂繁琐的部署流程变得非常简单 ...