码迷,mamicode.com
首页 > 其他好文 > 详细

数组名的理解

时间:2014-09-04 23:42:40      阅读:191      评论:0      收藏:0      [点我收藏+]

标签:数组名   const   数组指针   

数组名的再理解
先看下面的这段代码,程序会输出什么结果?
#include <stdio.h>

int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    int *p = (int *)(&a+1);

    printf("%d %d\n", *(a+1), *(p-1));

    return 0;
}
答案详见本文的最后。
先来一步步分析一下数组名到底是什么,首先看一下下面这段代码:
#include <stdio.h>

int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    int *p;

    p = a;

    return 0;
}
编译和运行都没有错误,说明a的值的类型直接赋给p是可以的,至少这说明了a的类型是属于可以直接赋值给p的类型中的一种,即a应该是一个指针类型的变量,而且这个指针类型变量的绝对不是int*类型的,因为在上面的程序中如果我们输出sizeof(a)和sizeof(p)的话可以看到一个输出的是20,一个输出的是4,证明这两个类型是不一样的,程序稍作修改:
#include <stdio.h>

int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    int *p;

    a = p;

    return 0;
}
编译器报错误:cannot convert from ‘int *‘ to ‘int [5]‘,然而这个int [5],C语言里并没有这种类型,这个类型其实很明显就是int a[5]把a去掉之后剩下的。暂时可以这样理解,a就代表的分配的20个字节的单元整体,同时a本身的值是这20个字节的起始地址,所以a是有两层含义的。再改一下程序:
#include <stdio.h>

int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    int *p;

    a ++;

    return 0;
}
编译器报错:‘++‘ needs l-value,这个错误的意思是++需要一个可以作为左值的操作对象,++唯一能够操作的就是变量,然而a根据上面的分析就是分配的一个20字节的变量,a的值也就是这20个字节变量的首地址,然而对a进行++操作却是不可以的,这个特点跟const修饰的变量时一致的。const修饰的变量相当于被赋予了只读属性,也就是说读取是可以的,写操作是非法的,所以const修饰的变量是不能做左值的,也就是不能被重新赋值的。再次修改一下例子:
#include <stdio.h>

int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    int *p;

    p = &a;

    return 0;
}
编译器报错:cannot convert from ‘int (*)[5]‘ to ‘int *‘,有了这个错误问题就越来越清晰了,对a的取地址操作得到的类型是int (*)[5],即一个数组指针,也就是说这个时候取地址操作对a的理解是一个20个字节的整体(5个int型的单元)。然而当采用p=a这种使用方法的时候,使用的是a的第二种理解方法就是取的是a的值,也就是这20个字节的起始地址。
再由C语言的优先级来分析最开始的题目,int *p = (int *)(&a+1)这条语句,&的优先级高于+,所以等同于int *p (int *)((&a)+1),这下来逐步分析,&a得到的是一个5个int型单元的数组指针,&a+1得到的就是这个指针加1的结果,也就是说现在的指针会指向a这20个字节后的第一个单元,这个单元的地址再被强制转换为int *类型赋值给p,所以p也就指向了a的20个字节后的第一个单元,所以*(p-1)取到的值就应该是p的前一个单元,也就是a的5个单元中最后的一个单元的值。所以得到最开头的程序输出为:2 5

数组名的理解

标签:数组名   const   数组指针   

原文地址:http://blog.csdn.net/laoniu_c/article/details/39062361

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!