2015-12-21 61 views
4

我正在通过玩具问题来理解C和C中指针和数组之间的区别,我偶然发现了一些我还没有寻找或寻找答案。(* b)[0] vs * b [0] - 数组和指针

我有以下程序

#include <stdio.h> 

int main() 
{ 
    int a[3][3] = {{1, 2, 3}, {4, 5,6}, {7, 8, 9}}; 
    int (*b)[3]; 

    b = a; 

    printf("%d %d %d\n", (*b)[0], (*b)[1], (*b)[2]); 
    printf("%d %d %d\n", *b[0], *b[1], *b[2]); 

    b++; 
    printf("%d %d %d\n", (*b)[0], (*b)[1], (*b)[2]); 

    b++; 
    printf("%d %d %d\n", (*b)[0], (*b)[1], (*b)[2]); 

    return 0; 
} 

当我编译并运行它,我得到这个:

[email protected]: clang -g q.c -o q.o                  
[email protected]: ./q.o 
1 2 3 
1 4 7 
4 5 6 
7 8 9 

我的问题是什么(*b)[0]*b[0]之间的区别?看起来前者是int *型,而后者是int *[3]型。如何解释操作人员*[]()来认识这一点?

回答

3

int (*b)[3];是一个数组指针,一种特殊类型的指针,可以指向整个数组而不仅仅指向第一个元素。不要与int *b[3]混淆,这是一个3个指针的数组,并且不存在于您的代码中。

b=a将b设置为指向二维数组a中的第一个元素,它是一维数组。

当您取消引用数组指针时,您将获得数组。当一个数组在表达式中使用时,它将“衰减”为指向第一个元素的指针,这解释了第一个printf行。

如果你写*b[0],那么[]的运算符优先级高于*,所以它的意思是“给我数组编号0,它会衰减成指向第一个元素的指针,给我该元素的内容”。

对于任何指针类型,包括数组指针,指针增量为b遵循指针算术规则:增加地址,以便指针指向内存中下一个相邻类型的指针。也就是说,在这个例子中增加地址sizeof(*b)字节,这将是3*sizeof(int)

+0

啊,我应该有一个知道我曾经写过运算符来考虑运算符的优先级。你的回答为我清除了一些事情。 – Idr

0

(*b)[0]首先解引用指针,然后做索引访问。它相当于*((*b)+(0))

*b[0]先做索引访问然后解引用指针。它相当于**((b)+(0))

加零意味着什么都没有,所以他们都相当于**bint型,所以几乎没有任何区别。

2

这只适用于二维数组,而不适用于任何随机指针。

当使用(*b)[1]时,首先完成解引用,然后是索引,所以它实际上意味着b[0][1],并且您从第一个数组中获取值。

如果您使用*b[1],它与*(b[1])相同。索引操作符将首先被处理,然后被解引用,所以你得到了b[1][0]

1

我的问题是(* b)[0]和* b [0]之间的区别是什么?

int (*b)[3] ;是指针大小3的一个维阵列。在这种情况下,第一取消引用指针,然后执行由于()索引访问。

*b[3]是3个指针的数组,在这种情况下首先做索引访问,因为[];因为这一点

当在第一printf

printf("%d %d %d\n", (*b)[0], (*b)[1], (*b)[2]); 

printf("%d %d %d\n", *b[0], *b[1], *b[2]); 

正在打印第一一个维阵列的元件在第二printf它指向每一行的第一个元素。

b++在第一种情况下指向第二个数组,第二种情况是printf它指向每行的第二个元素。

0

b是指向数组s的指针。在作业中

b = a; 

a将衰减为指向其第一个元素。由于a是一组数组,因此它的第一个元素是和数组3int s。因此,上面的语句相当于

b = &a[0]; 

所以,b指向阵列a[0]。可以使用索引a[0][i]访问数组a[0]的元素。在指针算术等效中,它是*(*(a + 0) + i) = *(*(a) + i) = *(*a + i) = (*a)[i]
在表达式(*a)[i]中转换后的a的类型是int (*)[3],其也是b的类型。因此,也可以使用(*b)[i]访问数组a[0]
所以,声明

printf("%d %d %d\n", (*b)[0], (*b)[1], (*b)[2]); 

相当于

printf("%d %d %d\n", (*a)[0], (*a)[1], (*a)[2]); 

printf("%d %d %d\n", a[0][0], a[0][1], a[0][2]); 

现在看*b[0]。根据运营商优先权规则,*b[0]等同于*(b[0])。简单的b[0]表示如上所述的数组a[0],并且当在表达式中使用时将数组转换为指向其第一个元素的指针,除了一些例外,b[0]实际上是指向表达式*(b[0])中的元素a[0][0]的指针。 *中的()取消引用此指针并给出值&a[0][0]。同样,*b[1]*b[2]正在给出地址&a[1][0]&a[2][0]上的元素。
因此,声明

printf("%d %d %d\n", *b[0], *b[1], *b[2]); 

相当于

printf("%d %d %d\n", *a[0], *a[1], *a[2]);  

printf("%d %d %d\n", &a[0][0], &a[0][1], &[0][2]); 

这将导致一个结论,(*b)[0]*b[0]都是同一类型的,int

0

有点迟到了,但答案似乎错过一些重要的点。 (* b)[0]和* b [0]之间的区别是什么?

(* b)[0]和* b [0]之间的区别是什么?

提供b是3 int类型的指针数组,并指向一个

int (*b)[3] = a; // int a[3][3] 

避免一些混乱,让说一个b

int a[X][Y];  // in your example, X=Y=3 
int (*b)[Y] = a; // this line probably gives some clue about what b is 

这是precedence的问题。 []优先*,这意味着

  • ,如果你不把父母*b[0]b[0]首先计算并产生int [Y],第一[Y]阵列的[X][Y],然后*应用和衰减(解除引用)变成int,该数组的第一个int为Y
    结果(或目标)是int in a[0][0]

  • 与父母,(*b)[0]*b被评估第一产生一个int [Y],第一个,则该[0]给出[Y]的第一INT
    结果(或目标)是int in a[0][0]。再次......真的吗?

两个[0]是不一样的东西!混淆来自第一个元素的*[0]收益率,但是在两种情况下,评估顺序都不相同。

相关问题