zoukankan      html  css  js  c++  java
  • C中指针和数组引发的探索二

           在上一篇文章中分析了指针与数组的区别,包括编译器内存分配概况:http://www.cnblogs.com/guoyuanwei/archive/2012/06/05/2535413.html 

    这篇文章将主要研究下指针和数组间相同点。

    在1978年7-8月,The Bell System Technical Journal,57卷,6号,第1991-2019页中提到:“当一个数组名出现在一个表达式中时,它会被转换为一个指向该数组第一个元素的指针

    1、“表达式中的数组名就是指针”如下代码

           int a[10], *p, i=2;

           p=a; p[i];

          上面的代码表示取p[i]的值,可以看到这时指针和数组是一样的用法。实际上对数组的引用如a[i]在总是被编译器编译为*(a+1),这个是C语言的标准规定的,因此编译器的设计者,都遵循

    了这个规律,因此在一个表达式中数组名也就成了指针。

    2、“C语言把数组下标[]作为指针的偏移量”处理

           产生这个现象的根本原因在与硬件机制,指针和偏移量是底层硬件所使用的基本模型

    3、 “作为函数参数的数组名等于指针”

          在C标准中规定,在函数形参这个特殊情况下,编译器必须把数组形式改写成指向数组第一个元素的指针形式。编译器只向该函数传递数组的地址,而不是整个数组的拷贝,编译器之所以这样做,主要从效率方面考虑,如果拷贝整个数组,无论在时间上还是在内存空间上开销都比较大。因此C语言标准中规定:“所有数组在作为参数传递时,都转换为指向数组起始地址的指针,而其它参数均采用传值调用”,这样也可以简化编译器的设计。

          同理函数的返回值也不可能是一个数组,只能是指向数组的指针。这里实际上体现出了一个“传值”与“传址”的区别,这在其它编程语言如C++,C#都有这样的区别。在函数内部使用指针,所能进行的对数组的操作几乎跟传递原本的数组没啥差别。但是如果想用sizeof(实参)来获取数组的长度,得到的结果并不是数组的长度。如下面代码:

     void Fun7(char *a);
    void Fun8(char a[]);

    int main(int argc,char*argv[])
    {

    char s1[]="abcdef";  
     char *s2="abcdef";
     Fun7(s1);
     Fun8(s1);

    void Fun7(char *a)
    {
      printf("%d",sizeof(a)) ;
      printf("%s",a);

    }

    void Fun8(char a[])
    {
      printf("%d",sizeof(a)) ;
      printf("%s",a);
    }

       函数Fun7和Fun8被调用,执行的结果是一样的,但是里面sizeof(a)值并不是数组的大小6,而为4,因为a代表的是一个指针,指针的大小就是4个字节,这也证明了上面的分析。为了进一步的理解这个问题,输入下面的代码,先分析输出的情况:

    #include<stdio.h>
    void fun1(char *s);
    int main(void)
    {
        char a[]="abcdefg";
        fun1(a);
        char c=getchar();
    }

    void fun1(char *s)
    {
        printf("%d\n",s);
        printf("%d\n",&s);
        printf("%d\n",&(s[0]));
        printf("%d\n",&(s[1]));
    }

    上面的代码将一个字符数组当作参数传入,

    printf("%d\n",s)这条语句应该输出的是指针变量s的值,也就是数组元素的首地址;

    printf("%d\n",&s);这条语句应该输出的是编译器给实参s分配的地址,是一个栈区域的地址值;

    printf("%d\n",&(s[0]));这条语句应该输出的是数组中第一个元素的地址值;与printf("%d\n",s)结果应该相同。

    printf("%d\n",&(s[1]));输出的是数组中第2个元素的地址值。比printf("%d\n",s)输出值大1

    运行上面的代码,结果如下:

    可以看到与分析的一致。

  • 相关阅读:
    2014/11/25 函数
    2014/11/24 条件查询
    2、计算器
    1、winform数据库调用(基本方法)
    1、网页基础
    14、函数输出参数、递归
    13、C#简易版 推箱子游戏
    12、函数
    11、结构体、枚举
    10、特殊集合
  • 原文地址:https://www.cnblogs.com/guoyuanwei/p/2537199.html
Copyright © 2011-2022 走看看