zoukankan      html  css  js  c++  java
  • char * 与char []探究理解

    问题引入

    以前一直认为二者是一样的,今天突然发现他们还是有很大的不同的。例如char *a = "abc"和char b[] = "abc",当我使用strcat(b,a)时得到的b是二者的结合,当我使用strcat(a,b)时系统报错。也就是说前者改变其内容程序是会崩溃的,而后者完全正确。

    预备知识

    内存分配的三种方式方式:静态存储区、堆区和栈区。它们的功能不同,使用方式也就不同。

    1.静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。

    2.栈区:在执行函数时,函数(包括main函数)内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。(任何变量都处于站区,例如int a[] = {1, 2},变量a处于栈区。数组的内容也存在于栈区。)

    3.堆区:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或delete释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。 但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,并立即将指针置位NULL,防止产生野指针。

    解决问题

    回到问题上来,我们来举个例子:char *a = "Hello",char b[] = "World",其中a是指向字符串第一个字符'H'的一个指针,b也是指向字符数组第一个字符'W'的指针,但这二者不相同,不同在哪呢?

    char *a = "Hello":定义了一个char型的指针a,a在栈上,指向"Hello"所在的内存单元,它不知道这个内存单元有多大。"Hello"存放在常量区,是无法修的。通过指针a只可以访问字符串常量,而不可以改变它。它在编译时就会被确定。

    char b[] = "World":定义一个字符数组,在栈上开了一块区域,b为这块区域的首地址。"World"是存放在这块区域中,是可以修改的。可以通过指针b去访问和修改数组内容。它要在运行时才会被确定。

    贴段代码理解一下:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    int main()
    {
        char *a="Hello";//a在栈上,"Hello"在常数区上
        //a[2]='a';//系统错误:不可以修改常数区数据,只能读取
        char b[]="Hello";//b在栈上,且为字符串"Hello"的首地址
        b[2]='a';//可以这样做,可以修改
    
        char *s1=(char*)malloc(64);//在栈上开辟一个区域放s1,在堆上开辟一个区域,再让s1指向他
        char s2[64];
    
        while(~scanf("%s %s",s1,s2))
        {
            char *s3=s2;//此时s3与s2用法一样,因为他们指向同一个在栈上的地方
            s3[2]='a';
            printf("%s %s %s
    ",s1,s2,s3);
        }
    }

    结论

    在C/C++中,指针和数组在很多地方可以互换使用,这使得我们产生一种错觉,感觉数组和指针两者是完全等价的,事实上数组和指针是有很大的区别的。

    数组对应着一块内存区域,而指针是指向一块内存区域,其地址和容量在生命期里不会改变,只有数组的内容可以改变;而指针却不同,它指向的内存区域的大小可以随时改变,而且当指针指向常量字符串时,它的内容是不可以被修改的,否则在运行时会报错。

    用运算符sizeof可以计算出数组的容量(字节数),而用sizeof却无法计算指针所指内存的容量,用sizeof(p)得到的结果永远是4或者2(即指针变量所占内存单元的字节数,一般情况下指针变量占2个或4个字节的内存单元)。在进行参数传递时,数组会自动退化为同类型的指针。

    在使用过程中,我们可以给char*开辟空间,例如char *s=(char*)malloc(64);这个空间实在堆上的,使用起来就和字符数组很像了(几乎一样)

    char* 类型使用总结:http://blog.csdn.net/z702143700/article/details/46628251

    C语言字符串处理函数:http://www.cnblogs.com/alaigle/archive/2012/05/24/2516062.html

    作者: AlvinZH

    出处: http://www.cnblogs.com/AlvinZH/

    本人Github:https://github.com/Pacsiy/JobDu

    本文版权归作者AlvinZH和博客园所有,欢迎转载和商用,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    重登陆模式 --ESFramework 4.0 快速上手(07)
    信息处理,分而治之-- ESFramework 使用技巧
    ESFramework 4.0 有哪些优点?
    铁血规则:事件预订与取消预订
    聊天系统Demo,增加文件传送功能(附源码)-- ESFramework 4.0 快速上手(14)
    判定生死的心跳机制 --ESFramework 4.0 快速上手(07)
    Spring中bean注入前后的一些操作:
    Spring中注入List,Set,Map,Properties
    Spring MVC视图解析器:配置多个视图解析器的优先级
    Spring 3 MVC And JSR303 @Valid Example
  • 原文地址:https://www.cnblogs.com/AlvinZH/p/6815414.html
Copyright © 2011-2022 走看看