int(*a)[3]的解读 [英] Interpretation of int (*a)[3]

查看:86
本文介绍了int(*a)[3]的解读的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 C 中使用数组和指针时,人们很快就会发现它们绝不是等价的,尽管乍一看似乎如此.我知道 L 值和 R 值的差异.不过,最近我试图找出可以与二维数组结合使用的指针的类型,即

When working with arrays and pointers in C, one quickly discovers that they are by no means equivalent although it might seem so at a first glance. I know about the differences in L-values and R-values. Still, recently I tried to find out the type of a pointer that I could use in conjunction with a two-dimensional array, i.e.

int foo[2][3];
int (*a)[3] = foo;

但是,尽管 *[] 有常规的运算符优先级规则,我还是无法弄清楚编译器如何理解" a 的类型定义.相反,如果我使用 typedef,问题就会变得明显简单:

However, I just can't find out how the compiler "understands" the type definition of a in spite of the regular operator precedence rules for * and []. If instead I were to use a typedef, the problem becomes significantly simpler:

int foo[2][3];
typedef int my_t[3];
my_t *a = foo;

最后,有人可以回答我关于编译器如何读取术语 int (*a)[3] 的问题吗?int a[3] 很简单,int *a[3] 也很简单.但是,为什么不是int *(a[3])?

At the bottom line, can someone answer me the questions as to how the term int (*a)[3] is read by the compiler? int a[3] is simple, int *a[3] is simple as well. But then, why is it not int *(a[3])?

当然,我的意思不是typecast",而是typedef"(这只是一个错字).

Of course, instead of "typecast" I meant "typedef" (it was just a typo).

推荐答案

首先,你的意思是typedef";不是类型转换"在你的问题中.

First, you mean "typedef" not "typecast" in your question.

在 C 中,指向 T 类型的指针可以指向 T 类型的对象:

In C, a pointer to type T can point to an object of type T:

int *pi;
int i;
pi = &i;

以上简单易懂.现在,让我们让它更复杂一点.您似乎知道数组和指针之间的区别(即,您知道数组不是指针,但有时它们的行为与它们相似).所以,你应该能够理解:

The above is simple to understand. Now, let's make it a bit more complex. You seem to know the difference between arrays and pointers (i.e., you know that arrays are not pointers, they behave like them sometimes though). So, you should be able to understand:

int a[3];
int *pa = a;

但为了完整起见:在赋值中,名称 a 等价于 &a[0],即指向第一个元素的指针数组a.如果您不确定它的工作原理和原因,有很多答案可以准确地解释数组的名称何时衰减".指向一个指针,当它没有时:

But for completeness' sake: in the assignment, the name a is equivalent to &a[0], i.e., a pointer to the first element of the array a. If you are not sure about how and why this works, there are many answers explaining exactly when the name of an array "decays" to a pointer and when it does not:

  • My answer to a question titled type of an array,
  • Another answer with examples of instances when the name of an array does not decay to a pointer, and
  • The answers to what is array decaying.

我相信在 SO 上还有更多这样的问题和答案,我只是提到了我从搜索中找到的一些.

I am sure there are many more such questions and answers on SO, I just mentioned some that I found from a search.

回到主题:当我们有:

int foo[2][3];

foo 的类型是array [2] of array [3] of int";.这意味着 foo[0] 是 3 个 int 的数组,而 foo[1] 是 3 个 int 的数组s.

foo is of type "array [2] of array [3] of int". This means that foo[0] is an array of 3 ints, and foo[1] is an array of 3 ints.

现在假设我们要声明一个指针,并将其分配给 foo[0].也就是说,我们想做:

Now let's say we want to declare a pointer, and we want to assign that to foo[0]. That is, we want to do:

/* declare p somehow */
p = foo[0];

以上与int *pa = a;行的形式没有区别,因为afoo[0]是一样的.所以,我们需要 int *p; 作为我们对 p 的声明.

The above is no different in form to the int *pa = a; line, because the types of a and of foo[0] are the same. So, we need int *p; as our declaration of p.

现在,关于数组要记住的主要事情是规则"关于数组的名称衰减为指向其第一个元素的指针仅适用一次.如果您有一个数组的数组,那么在值上下文中,数组的名称不会衰减为指向指针的指针"类型,而是变为指向数组的指针".回到foo:

Now, the main thing to remember about arrays is that "the rule" about array's name decaying to a pointer to its first element applies only once. If you have an array of an array, then in value contexts, the name of the array will not decay to the type "pointer to pointer", but rather to "pointer to array". Going back to foo:

/* What should be the type of q? */
q = foo;

上面的名字foo是指向foo的第一个元素的指针,即我们可以把上面写成:

The name foo above is a pointer to the first element of foo, i.e., we can write the above as:

q = &foo[0];

foo[0] 的类型是int 的数组[3]".所以我们需要 q 是一个指向 int 的array [3]"的指针:

The type of foo[0] is "array [3] of int". So we need q to be a pointer to an "array [3] of int":

int (*q)[3];

q 的括号是必需的,因为 [] 在 C 中比 * 绑定得更紧密,所以 int *q[3]q 声明为一个指针数组,我们想要一个指向数组的指针.int *(q[3]) 从上面开始,等价于 int *q[3],即一个由 3 个指向 int.

The parentheses around q are needed because [] binds more tightly than * in C, so int *q[3] declares q as an array of pointers, and we want a pointer to an array. int *(q[3]) is, from above, equivalent to int *q[3], i.e., an array of 3 pointers to int.

希望有所帮助.您还应该阅读 C for smarties: arrays and pointers 以获得非常好的教程关于这个话题.

Hope that helps. You should also read C for smarties: arrays and pointers for a really good tutorial on this topic.

关于阅读声明的一般性:您从变量"的名称开始由内而外"阅读它们;(如果有的话).除非紧邻的右侧有 [] ,否则您尽可能向左走,并且您始终遵守括号.cdecl 应该能在一定程度上帮助你:

About reading declarations in general: you read them "inside-out", starting with the name of the "variable" (if there is one). You go left as much as possible unless there is a [] to the immediate right, and you always honor parentheses. cdecl should be able to help you to an extent:

$ cdecl
cdecl> declare p as  pointer to array 3 of int
int (*p)[3]
cdecl> explain int (*p)[3]
declare p as pointer to array 3 of int

阅读

int (*a)[3];

      a            # "a is"
    (* )           # parentheses, so precedence changes.
                   # "a pointer to"
        [3]        # "an array [3] of"
int        ;       # "int".

为了

int *a[3];

     a             # "a is"
      [3]          # "an array [3] of"
    *              # can't go right, so go left.
                   # "pointer to"
int      ;         # "int".

为了

char *(*(*a[])())()

          a         # "a is"
           []       # "an array of"
         *          # "pointer to"
        (    )()    # "function taking unspecified number of parameters"
      (*        )   # "and returning a pointer to"
                 () # "function"
char *              # "returning pointer to char"

(来自 c-faq 问题 1.21 的示例.在实践中,如果你正在阅读如此复杂的声明,那么代码就有严重错误!)

(Example from c-faq question 1.21. In practice, if you are reading such a complicated declaration, there is something seriously wrong with the code!)

这篇关于int(*a)[3]的解读的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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