• C中“指针和数组”引发的探索一


          大二开始学习C语言,一晃几年过去了,一直在追赶新技术,底层的东西确总感觉没吃透,今日有空,查阅了许多资料后,有感而发,觉得一定要写下来,万一忘记了,以后也可以查阅。

    再论数组和指针:

    (1)区分C语言中的声明和定义

        声明只是告诉编译器变量的类型和名字,定义才是真真决定内存分配的地方,在一个C程序中,定义只能有一个,而声明却可以有多个。  

             如文件1中代码:int a[10]; 定义数组,编译器会为数组a分配10个整型的内存

             如文件2中代码:extern int a[];声明一个外部的数组,指向文件1中编译器分配了内存的变量a,声明中并不进行内存分配,所以可以不用指定数组大小

            如文件3中代码:extern int a[];也声明一个外部的数组,也指向文件1中编译器分配了内存的变量a,声明中并不进行内存分配,所以可以不用指定数组大小

    (2)左值和右值的问题

           如 a=b;这样一条简单的语句,蕴含着许多微妙之处,这也从另外一个方面体现了C语言中指针的精髓。指针的值(地址)与指针所的指向(地址中放的内容)

           这里a出现在等号左边,为左值,代表的含义是a所代表的地址,在编译时就确定了,左值表示存储结果的地方。

           这里的b出现在等号右边,为右值,代表的含义是b所对应的地址的内容,右值在程序运行时才能知道。

           C语言中有个非常重要的特性“可修改的左值”

           如:int a=10;

                int b=100;

                a=b;

            上面代码是能够正确运行的,但是这个特性确对数组不适应,我们知道数组名也相当于一个地址值,也是左值,但它不能作为赋值对象

            如: int a[10]; 
                  int b[10];
                  a=b; //错误,a不是可以修改的左值

            我们正常的理解等号左边的值应该都是可以赋值的,但是对数组例外,因此C语言中产生了“可修改的左值”这样的特殊术语。

    (3) char * s1=“abcdefg”与char s2[]="abcdefg"的区别

             在剖析它的区别之前,有必要先分析下C程序的内存分布情况,    

          上图左边为内存分布描述,中间为一段代码,箭头指向了所在的内存区域,右边为在VS2010里面调试时监视得到的个变量的值,这里着重讨论下char  s1[]=“abcdefg”与char *s2="abcdefg"的区别:

           s2为一个指针,指向的是字符串的首地址,s1为字符数组,其值也是指向的是字符串的首地址。尽管这两个字符串均为:“abcdefg”,但编译器对它们分配的存储空间有本质的区别,从上图左右边监视的结果就可知,s1的值为0x0012ff40且s1自己地址值也为0x0012ff40,这说明s1分配在栈空间上,且对应的字符串也在栈空间上。

         再观察指针变量s2其值为0x0041573c,s2本身的地址值为0x0012ff34,这说明了s2本身这个符号被分配在了栈空间上,但是其指向的内容"abcdefg"却是在文字常量区。

     正是这个本质的差别,导致了指针和数组访问方式的不同,如下代码:

              char s1[]="abcdefg" ; char c= s1[1];编译器符号表s1具有一个确定的地址值0x0012ff40,运行时由于取偏移量1与0x0012ff40相加,取相加后地址值的内容。

              char *s2="abcdefg"; char c=s2[1];编译器符号表s2具有一个确定的地址0x0012ff34,运行时取0x0012ff34中的内容即为0x0041573c,将偏移量1与0x0041573c相加,

       取相加后的地址中的内容。

            比较上面两种方式,指针多了一个步骤。

          指针所对应的字符串是不能被修改的;而数组却可以

     也就是说下面代码是错误的:

     char *s2="abcdef";
     s2[1]='k';

     运行时会出现如下图错误:

     而通过数组就可以修改,如代码:

    char s1[]="abcdef";
    s1[1]='k';

    导致这个区别的根本原因就在上面的内存分配上,一个在栈区,一个在文字常量区。

  • 相关阅读:
    R语言ECM误差修正模型、均衡修正模型、受限VECM、协整检验、单位根检验即期利率市场数据
    R语言MCMC的lme4二元对数Logistic逻辑回归混合效应模型分析吸烟、喝酒和赌博影响数据
    检测异常值的4种方法和R语言时间序列分解异常检测
    R语言LME4混合效应模型研究教师的受欢迎程度|附代码数据
    用了那么久的Lombok,你知道它的原理么?
    ModelScope初探:一行代码调用成熟AI模型。
    RocketMQ 消息集成:多类型业务消息——定时消息
    浅谈数据仓库架构设计
    MSE 治理中心重磅升级流量治理、数据库治理、同 AZ 优先
    一文剖析PolarDB HTAP的列存数据压缩
  • 原文地址:https://www.cnblogs.com/guoyuanwei/p/2535413.html
Copyright © 2020-2023  润新知