是一个,&放大器;一,*一个,一个[0],&放大器;一个[0]和&放大器;一个[0] [0]相同指针? [英] Are a, &a, *a, a[0], &a[0] and &a[0][0] identical pointers?

查看:151
本文介绍了是一个,&放大器;一,*一个,一个[0],&放大器;一个[0]和&放大器;一个[0] [0]相同指针?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下的C程序:

#include <stdio.h>

int main(){
    int a[2][2] = {1, 2, 3, 4};
    printf("a:%p, &a:%p, *a:%p \n", a, &a, *a);
    printf("a[0]:%p, &a[0]:%p \n", a[0], &a[0]);
    printf("&a[0][0]:%p \n", &a[0][0]);
    return 0;
}

它提供了以下的输出:

It gives the following output:

a:0028FEAC, &a:0028FEAC, *a:0028FEAC
a[0]:0028FEAC, &a[0]:0028FEAC
&a[0][0]:0028FEAC

我无法理解为什么&放大器;一个 A *一个 - 所有相同。同为 A [0] &放大器;一个[0] &放大器;一[0] [0]

I am not able to understand why are &a, a, *a - all identical. The same for a[0], &a[0] and &a[0][0].

编辑:

感谢答案,我明白了为什么这些数值走出来是平等的原因。这条线从书的 Kernighan的&安培;里奇的竟然是关键,我的问题:

Thanks to the answers, I've understood the reason why these values are coming out to be equal. This line from the book by Kernighan & Ritchie turned out to be the key to my question:

 the name of an array is a synonym for the location of the initial element.

所以,这个,我们得到

So, by this, we get

A = &放大器;一个[0]

A [0] = &安培; A [0] [0] (考虑作为数组的数组)

a[0] = &a[0][0] (considering a as an array of arrays)

直观地说,现在的原因是输出落后清楚。但是,考虑到指针如何用C语言实现,我无法理解如何 A &放大器;一个相等。我假设有一个变量 A 在内存中,它指向数组(这个数组的内存块的起始地址是这个变量的值 A )。

Intuitively, now the reason is clear behind the output. But, considering how pointers are implemented in C, I can't understand how a and &a are equal. I am assuming that there is a variable a in memory which points to the array(and the starting address of this array-memory-block would be the value of this variable a).

但是,当我们做&放大器;一个,并不意味着服用的内存位置的地址,其中的变量 A 储存?为什么这些值等于呢?

But, when we do &a, doesn't that mean taking the address of the memory location where the variable a was stored? Why are these values equal then?

推荐答案

他们不是的相同的指针。他们是不同类型的指针都指向同一个内存位置。相同的值(在某种程度上),不同的类型。

They're not identical pointers. They're pointers of distinct types that all point to the same memory location. Same value (sort of), different types.

在C A的二维数组是没有多于或少于数组的数组。

A 2-dimensional array in C is nothing more or less than an array of arrays.

对象 A 的类型为 INT [2] [2] ,或2元的2阵列的-element阵列 INT

The object a is of type int[2][2], or 2-element array of 2-element array of int.

数组类型的任何Ex pression是,在大多数但不是所有的上下文中,隐式转换为(衰变)一个指向数组对象的第一个元素。所以的前pression A ,除非它是一元的操作数​​&安培; 的sizeof ,类型为 INT(*)[2] ,并且是等同于 &安培; A [0] (或及(A [0])如果这是更清晰)。变得到行2维阵列的0的指针。要记住,这是一个指针是很重要的的(或等价的的地址的),而不是一个指针的对象的;没有指针的对象在这里,除非你明确地创建一个。

Any expression of array type is, in most but not all contexts, implicitly converted to ("decays" to) a pointer to the array object's first element. So the expression a, unless it's the operand of unary & or sizeof, is of type int(*)[2], and is equivalent to &a[0] (or &(a[0]) if that's clearer). It becomes a pointer to row 0 of the 2-dimensional array. It's important to remember that this is a pointer value (or equivalently an address), not a pointer object; there is no pointer object here unless you explicitly create one.

所以在看的几个前pressions你问一下:

So looking at the several expressions you asked about:


  • &放大器;一个是整个数组对象的地址;这类型的指针前pression INT(*)[2] [2]

  • A 是数组的名字。如上所讨论的,它衰减的指针数组对象的第一个元素(行)。这类型的指针前pression INT(*)[2]

  • *一个解引用的指针前pression A 。由于 A (它衰变后)是指向数组2 INT S, *一个是2 INT 秒的数组。因为这是一个数组类型,它衰变(在大多数但不是所有的上下文)的指针数组对象的第一个元素。因此,这类型的为int * *一个等同于&安培; A [0] [0]

  • &放大器;一个[0] 是数组对象的第一(0)行的地址。这类型的 INT(*)[2] A [0] 是一个数组对象;它不会腐烂的指针,因为它是一元&放大器的直接操作;

  • &安培; A [0] [0] 是数组对象的0行元素0的地址。这类型的为int *

  • &a is the address of the entire array object; it's a pointer expression of type int(*)[2][2].
  • a is the name of the array. As discussed above, it "decays" to a pointer to the first element (row) of the array object. It's a pointer expression of type int(*)[2].
  • *a dereferences the pointer expression a. Since a (after it decays) is a pointer to an array of 2 ints, *a is an array of 2 ints. Since that's an array type, it decays (in most but not all contexts) to a pointer to the first element of the array object. So it's of type int*. *a is equivalent to &a[0][0].
  • &a[0] is the address of the first (0th) row of the array object. It's of type int(*)[2]. a[0] is an array object; it doesn't decay to a pointer because it's the direct operand of unary &.
  • &a[0][0] is the address of element 0 of row 0 of the array object. It's of type int*.

所有这些指针前pressions的指代相同的位置在存储器中。该位置是数组对象的开始 A ;它也是数组对象的开头 A [0] INT 对象的 A [0] [0]

All of these pointer expressions refer to the same location in memory. That location is the beginning of the array object a; it's also the beginning of the array object a[0] and of the int object a[0][0].

打印指针的值正确的方法是使用%P格式的的指针值转换为无效*

The correct way to print a pointer value is to use the "%p" format and to convert the pointer value to void*:

printf("&a = %p\n", (void*)&a);
printf("a  = %p\n", (void*)a);
printf("*a = %p\n", (void*)*a);
/* and so forth */

这转化为无效* 产生,指定只在内存中的位置,而不是什么类型的对象是在那个位置的原始的地址。所以,如果你有不同的类型的指向开始在同一个内存位置的对象多个指针,它们全部转换为无效* 产生相同的值。

This conversion to void* yields a "raw" address that specifies only a location in memory, not what type of object is at that location. So if you have multiple pointers of different types that point to objects that begin at the same memory location, converting them all to void* yields the same value.

(我已经掩盖了的 [] 索引操作符的内部运作。这位前pression X [Y] 是定义等同于 *(X + Y),其中 X 是一个指针(可能数组的隐式转换的结果)和是一个整数(反之亦然),但是这是丑陋的。改编[0] 0 [ARR] 是等价的,但是,只有当你在写故意混淆code是非常有用的。如果我们考虑的对等,它需要一个段落左右来形容 A [0] [0] 表示,这个答案可能已经太长了。)

(I've glossed over the inner workings of the [] indexing operator. The expression x[y] is by definition equivalent to *(x+y), where x is a pointer (possibly the result of the implicit conversion of an array) and y is an integer. Or vice versa, but that's ugly; arr[0] and 0[arr] are equivalent, but that's useful only if you're writing deliberately obfuscated code. If we account for that equivalence, it takes a paragraph or so to describe what a[0][0] means, and this answer is probably already too long.)

有关完整起见三种上下文中,数组类型的前pression是的的隐式转换为指向数组的第一个元素是:

For the sake of completeness the three contexts in which an expression of array type is not implicitly converted to a pointer to the array's first element are:


  • 当它是一元&放大器的操作; ,所以&放大器;改编得到整个数组对象的地址

  • 当它的中的sizeof 操作数,因此 sizeof的改编收益率大小的数组对象,而不是字节指针的大小;和

  • 当它在用于初始化数组(子)对象的初始化字符串文字,所以个char [6] =你好; 拷贝数组值到取值,而不是胡说初始化一个指针值数组对象。 c您要问这最后一个异常并不适用于$ C $。

  • When it's the operand of unary &, so &arr yields the address of the entire array object;
  • When it's the operand of sizeof, so sizeof arr yields the size in bytes of the array object, not the size of a pointer; and
  • When it's a string literal in an initializer used to initialize an array (sub-)object, so char s[6] = "hello"; copies the array value into s rather than nonsensically initializing an array object with a pointer value. This last exception doesn't apply to the code you're asking about.

(参数 N1570 草案2011 ISO C标准错误地指出 _Alignof 是第四个例外,这是不正确的,因为 _Alignof 只能应用于带括号的类型名称,而不是一个前pression,误差在最终C11标准的修正。)

(The N1570 draft of the 2011 ISO C standard incorrectly states that _Alignof is a fourth exception; this is incorrect, since _Alignof can only be applied to a parenthesized type name, not to a expression. The error is corrected in the final C11 standard.)

推荐阅读:第6 comp.lang.c常见问题

这篇关于是一个,&放大器;一,*一个,一个[0],&放大器;一个[0]和&放大器;一个[0] [0]相同指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆