zoukankan      html  css  js  c++  java
  • 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';

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

  • 相关阅读:
    linux之awk命令
    HDU 2097 Sky数 进制转换
    HDU 2077 汉诺塔IV
    HDU 2094 产生冠军 dfs加map容器
    HDU 2073 叠框
    HDU 2083 简易版之最短距离
    HDU 2063 过山车 二分匹配
    天梯 1014 装箱问题
    天梯 1214 线段覆盖
    天梯 1098 均分纸牌
  • 原文地址:https://www.cnblogs.com/guoyuanwei/p/2535413.html
Copyright © 2011-2022 走看看