zoukankan      html  css  js  c++  java
  • C语言中对数组名取地址

    在C/C++中,数组名相当于一个指针,指向数组的首地址。这里“相当于”不代表等于,数组名和指针还是有很多区别的,这个在《C陷阱与缺陷》里有详尽的讲述。而这里要说的是对于数组名取地址的这么一个操作。

    如果声明有如下数组:

    int arr[5];

    那么,&arr这个操作得到了什么值呢?

    如果简单的认为arr就是一个指向数组首地址的指针的话,那么很自然会想到&arr得到的是一个指向存放arr这个指针的指针,也就是一个二级指针,然而事实却并不是这样。

    观察以下代码:

    int arr[5];
    printf("%p
    %p
    ", arr, &arr);
    
    int *pointer = new int[5];
    printf("%p
    %p
    ", pointer, &pointer);

    在我的电脑上运行的结果如下:

    0024FC08
    0024FC08
    0042B158
    0024FBFC

    我们可以看到,这里pointer这个指针确实如我们所想指向了不同的地址,但是,arr这个数组名的表现却和指针不同,arr和&arr指向的地址是一样的。

    这里便体现除了数组名和指针的一个不同之处:对数组名进行&操作,并不是取其地址,而是得到了指向整个数组的指针。也就是说,arr与&arr指向的是同一个地址,但是他们的类型不一样。arr相当于&arr[0],类型是int *,而&arr是指向整个数组的指针,类型是int (*)[5]。

    而这样的区别显然也会在对指针或者数组名的加减操作中体现出来,看如下代码:

    int arr[5] = { 1, 2, 3, 4, 5 };
    printf("%d
    ", *arr);
    printf("%d
    ", *(arr + 1));
    printf("%d
    ", *((int*)(&arr + 1)));
    printf("%d
    ", *((int*)(&arr + 1) - 1));

    输出为:

    1
    2
    -858993460
    5

    前两个输出是很好理解的,对指针的加一操作会使指针按照指针的类型移动相应的位置。

    第三行输出中,首先得到了指向整个数组的指针,对其进行加一操作,指针就指向了整个数组后面的地址,也就是5后面的地址,那么此时将其转化为int*类型再输出,就得到了该未初始化过的值。

    第四行输出中,过程为,指针指向5后面的地址,转为int*类型,此时的减一操作使指针移动一个int类型大小的地址空间,那么便指向了5。

    这种特性推广到二维至多维指针的情况下都是类似的。

  • 相关阅读:
    Atitit.数据索引 的种类以及原理实现机制 索引常用的存储结构
    Atitti 大话存储读后感 attilax总结
    Atitit 设计模式的本质思考】
    Atitit 深入理解抽象类与接口 attilax总结
    Atitit 动态调用webservice与客户端代理方式调用
    atitit. 深入理解Cohesion)原理ad  attilax大总结
    Atitit.软件开发的几大规则,法则,与原则Principle v3
    Atitti  onvif 设备发现与原理
    Atitit 边缘检测原理attilax总结
    Atitit wsdl的原理attilax总结
  • 原文地址:https://www.cnblogs.com/TX980502/p/6671127.html
Copyright © 2011-2022 走看看