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';

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

  • 相关阅读:
    递归函数的写法笔记
    Spring项目中执行Java脚本
    关于秒杀的系统架构优化思路
    分布式搜索引擎Elasticsearch性能优化与配置
    分布式搜索引擎ElasticSearch+Kibana (Marvel插件安装详解)
    分布式搜索引擎Elasticsearch的查询与过滤
    Linux 下编译升级 Python
    搭建通过 ssh 访问的 Git 服务器
    分布式搜索引擎Elasticsearch的简单使用
    PHP 源码学习之线程安全
  • 原文地址:https://www.cnblogs.com/guoyuanwei/p/2535413.html
Copyright © 2011-2022 走看看