zoukankan      html  css  js  c++  java
  • [转载]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 ", sizeof(a));
      printf("b memory size: %d bytes ", sizeof(b));
      printf("b elements: %d ", sizeof(b)/sizeof(int));
      return 0;
    }
      数组a为字符型,后面的字符串实际上占据6个字节空间(注意最后有一个标识字符串的结束)。从后面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 |    pch: | ◎----->  |abc |

         ______           ______      ______

    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

  • 相关阅读:
    JID 2.0 RC4 发布,高性能的 Java 序列化库
    FBReaderJ 1.6.3 发布,Android 电子书阅读器
    Arquillian 1.0.3.Final 发布,单元测试框架
    JavaScript 的宏扩展 Sweet.js
    Hypertable 0.9.6.5 发布,分布式数据库
    JRuby 1.7.0 发布,默认使用 Ruby 1.9 模式
    httppp 1.4.0 发布,HTTP响应时间监控
    Redis 2.6.0 正式版发布,高性能K/V服务器
    OfficeFloor 2.5.0 发布,IoC 框架
    XWiki 4.3 首个里程碑发布
  • 原文地址:https://www.cnblogs.com/hhddcpp/p/4261238.html
Copyright © 2011-2022 走看看