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 []的区别---之第一篇的更多相关文章

  1. 转载:eclipse 搭建SSH项目(第一篇)

    第一篇:原文地址:http://blog.csdn.net/aaaaaaaa0705/article/details/6288431(虽然没有具体的例子,不过逻辑性强点,比较容易看懂) SSH框架是最 ...

  2. Zookeeper 入门第一篇

    转载原文地址: ZooKeeper学习总结 第一篇:ZooKeeper快速入门 ZooKeeper学习总结 第二篇:ZooKeeper深入探讨 ZooKeeper学习第一期---Zookeeper简单 ...

  3. <转载>深入 理解char * ,char ** ,char a[ ] ,char *a[] 的区别

    C语言中由于指针的灵活性,导致指针能代替数组使用,或者混合使用,这些导致了许多指针和数组的迷惑,因此,刻意再次深入探究了指针和数组这玩意儿,其他类型的数组比较简单,容易混淆的是字符数组和字符指针这两个 ...

  4. [转载]char * 和char []的区别---之第二篇

    原文地址:http://blog.sina.com.cn/s/blog_74a4593801019keb.html main() { char *p="abc123ABC";//c ...

  5. C/C++中char* 与char []定义的区别

    转载请注明来自souldak,微博:@evagle Question: 给你一个字符串例如abb输出它包含的字符的所有可能排列. 例如abb输出3个:abb,bab,bba Answer: 假设我们自 ...

  6. [转载]MySQL之char、varchar和text的设计

    [转载]MySQL之char.varchar和text的设计 来源:https://www.cnblogs.com/billyxp/p/3548540.html 首先我们先普及一下常识: 1.char ...

  7. char* 和char[]的区别

    以下内容均来自互联网,系笔者汇总并总结. 1. 问题介绍 问题引入:在实习过程中发现了一个以前一直默认的错误,同样char *c = "abc"和char c[]="ab ...

  8. char *s="string"和char s[]="string"的区别

    char *s="string"的内容是不可以改的 void main() {     char* pStr1 = "Hello!";     char pSt ...

  9. 深入 理解char * ,char ** ,char a[ ] ,char *a[] 的区别

    转自:https://blog.csdn.net/liusicheng2008_liu/article/details/80412586 1 数组的本质 数组是多个元素的集合,在内存中分布在地址相连的 ...

随机推荐

  1. php安装redis扩展连接redis服务器

    扩展包的下载地址:https://github.com/nicolasff/phpredis/archive/2.2.4.tar.gz tar xf phpredis-2.2.4.tar.gz cd ...

  2. centos6.7下网络设置

    vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE="eth0"BOOTPROTO="static"   # ...

  3. PHP通过IP 获取 地理位置(实例)

    发布:JB02   来源:脚本学堂  分享一例php代码,实现通过IP地址获取访问者的地理位置,在php编程中经常用到,有需要的朋友参考下吧.本节内容:PHP通过IP获取地理位置 例子: 复制代码代码 ...

  4. Ubuntu 14.04 安装flash插件

    分别tar.gz和apt-get方法 第一种: adboe官网下载tar.gz,进入terminal 1.解压缩包,输入命令“tar -zxvf 软件包名字” 2.拷贝插件到mozilla目录,输入命 ...

  5. Java输出1~1000之间所有可以被3整除又可以被5整除的数

    主要在于判断是否能被整除,思路是用取余运算符%,取余结果为0就表示能被整除. 代码如下: public class NumDemo { public static void main(String a ...

  6. activity切换动画特效

    效果图: 结构图: 测试代码: 布局: <?xml version="1.0" encoding="utf-8"?> <LinearLayou ...

  7. python os模块使用方法

    os.path模块 basename('文件路径')    去掉目录路径,返回fname文件名  1 import os 2 os.path.basename('/Volumes/1.mp4')   ...

  8. 与谷歌测试工程师的对话 - from Google Testing Blog

    Conversation with a Test Engineer by Alan Faulner Alan Faulner谷歌的一名测试工程师,他工作在DoubleClick Bid Manager ...

  9. 刀哥多线程之03GCD 常用代码

    GCD 常用代码 体验代码 异步执行任务 - (void)gcdDemo1 { // 1. 全局队列 dispatch_queue_t q = dispatch_get_global_queue(0, ...

  10. VPN错误800、错误789

    VPN突然无法连接解决方法: 1. 单击“开始”,单击“运行”,键入“regedit”,然后单击“确定” 2. 找到下面的注册表子项,然后单击它:HKEY_LOCAL_MACHINE\System\C ...