“指向int”和“指向ints数组的指针”的区别

时间:2022-09-06 14:44:16
int main()
{
    int (*x)[5];                 //pointer to an array of integers
    int y[6] = {1,2,3,4,5,6};    //array of integers
    int *z;                      //pointer to integer

    z = y;
    for(int i=0;i<6;i++)
        printf("%d ",z[i]);

    x = y;
    for(int i=0;i<6;i++)
        printf("%d ",(*x)[i]);

    return 0;
}

Both the above printfs print numbers 1 through 6.
If both "pointer to array of integers" and "pointer to integer" can do the same thing, do they have the same internal representation?
EDIT: This code does give warnings when compiled as pointed out by the answers below, however it does print the values correctly both the time on my x86_64 machine using gcc

上面两个printfs都打印数字1到6。如果“指向整数数组的指针”和“指向整数的指针”可以做同样的事情,它们的内部表示是否相同?编辑:这段代码在编译时发出警告,如下面的答案所指出,但是它确实在我的x86_64机器上使用gcc来正确地打印值。

8 个解决方案

#1


16  

Firstly, your code will not compile. The array has type int[6] (6 elements), while the pointer has type int (*)[5]. You can't make this pointer to point to that array because the types are different.

首先,您的代码不会编译。数组的类型为int[6](6个元素),而指针类型为int(*)[5]。你不能让这个指针指向那个数组,因为类型不同。

Secondly, when you initialize (assign to) such a pointer, you have to use the & on the array: x = &y, not just a plain x = y as in your code.

其次,当您初始化(分配给)这样一个指针时,您必须使用& on数组:x = &y,而不只是在代码中使用简单的x = y。

I assume that you simply typed the code up, instead of copy-pasting the real code.

我假设您只是键入代码,而不是复制粘贴真实的代码。

Thirdly, about the internal representation. Generally, in practice, you should expect all data pointers to use the same internal representation. Moreover, after the above assignments (if written correctly), the pointers will have the same numerical value. The difference between int (*)[5] and int * exists only on the conceptual level, i.e. at the level of the language: the types are different. It has some consequences. For example, if you increment your z it will jump to the next member of the array, but if you increment y, it will jump over the whole array etc. So, these pointers do not really "do the same thing".

第三,关于内部代表性。通常,在实践中,您应该期望所有数据指针都使用相同的内部表示。此外,在上面的赋值之后(如果写得正确的话),指针将具有相同的数值。int(*)[5]和int *之间的差异仅存在于概念层面,即语言层面:类型不同。它有一些后果。例如,如果你增加z它会跳转到数组的下一个元素,但是如果你增加y,它会跳转到整个数组等等,所以这些指针并不是真的“做同样的事情”。

#2


11  

The short answer: There is a difference, but your example is flawed.

简短的回答是:有区别,但是你的例子是有缺陷的。

The long answer:

长回答:

The difference is that int* points to an int type, but int (*x)[6] points to an array of 6 ints. Actually in your example,

不同之处在于int*指向int类型,而int (*x)[6]指向一个6 int的数组。其实在你的例子中,

x = y;

is undefined** behavior, you know these are of two different types, but in C you do what you want. I'll just use a pointer to an array of six ints.

是未定义的**行为,你知道它们有两种不同的类型,但是在C语言中,你想做什么就做什么。我用一个指针指向一个有6个ints的数组。

Take this modified example:

把这个修改后的示例:

int (*x)[6];                 //pointer to an array of integers
int y[6] = {1,2,3,4,5,6};    //array of integers
int *z;                      //pointer to integer
int i;

z = y;
for(i = 0;i<6;i++)
    printf("%d ",z[i]);

x = y; // should be x = &y but leave it for now!

for(i = 0;i<6;i++)
    printf("%d ",x[i]); // note: x[i] not (*x)[i]

First,

首先,

1 2 3 4 5 6

Would be printed. Then, we get to x[0]. x[0] is nothing but an array of 6 ints. An array in C is the address of the first element. So, the address of y would be printed, then the address of the next array in the next iteration. For example, on my machine:

会被打印出来。然后,我们得到x[0]。x[0]只是一个包含6个int的数组。C中的数组是第一个元素的地址。因此,y的地址将被打印出来,然后是下一个迭代中的下一个数组的地址。例如,在我的机器上:

1 2 3 4 5 6 109247792 109247816 109247840 109247864 109247888 109247912

As you can see, the difference between consecutive addresses is nothing but:

正如你所看到的,相邻地址之间的区别就是:

sizeof(int[6]) // 24 on my machine!

In summary, these are two different pointer types.

总之,这是两个不同的指针类型。

** I think it is undefined behavior, please feel free to correct my post if it is wrong.

**我认为这是不明确的行为,如有错误请随时纠正。

#3


4  

Hope this code helps:

希望这段代码可以帮助:

int main() {

    int arr[5] = {4,5,6,7,8};        
    int (*pa)[5] = &arr;
    int *pi = arr;

    for(int i = 0; i< 5; i++) {
        printf("\n%d %d", arr[i], (*pa)[i]);    
    }

    printf("\n0x%x -- 0x%x", pi, pa);
    pi++;
    pa++;
    printf("\n0x%x -- 0x%x", pi, pa);
}

prints the following:

输出如下:

4 4
5 5
6 6
7 7
8 8
0x5fb0be70 -- 0x5fb0be70
0x5fb0be74 -- 0x5fb0be84 

UPDATE: You can notice that pointer to integer incremented by 4 bytes (size of 32 bit integer) whereas pointer to array of integer incremented by 20 bytes (size of int arr[5] i.e. size of 5 int of 32 bit each). This demonstrates the difference.

更新:您可以注意到,指向整数的指针增加了4个字节(32位整数的大小),而指向整数数组的指针增加了20个字节(int arr[5]的大小,即每个32位整数的大小)。这说明不同之处。

#4


3  

To answer your question from the title, from the comp.lang.c FAQ: Since array references decay into pointers, if arr is an array, what's the difference between arr and &arr?

从题目中回答你的问题,从题目中回答。由于数组引用会衰减成指针,如果arr是数组,那么arr和&arr有什么区别呢?

However, the code you've posted has other issues (you're assigning y, not &y to x, and y is a 6-element array, but *x is a 5-element array; both of these should generate compilation warnings).

但是,您发布的代码还有其他问题(您将y赋值,而不是&y赋值给x, y是一个6元素的数组,但*x是一个5元素的数组;两者都应该生成编译警告)。

#5


2  

Who knows - this code exhibits undefined behavior:

谁知道呢?这段代码显示了未定义的行为:

printf("%d ",(*x)[i]);

#6


2  

Hope this code helps.

希望这段代码有帮助。


#include <stdio.h>
#include <stdlib.h>
#define MAXCOL 4
#define MAXROW 3

int main()
{      
      int i,j,k=1;
      int (*q)[MAXCOL];      //pointer to an array of integers

      /* As malloc is type casted to "int(*)[MAXCOL]" and every 
         element (as in *q) is 16 bytes long (I assume 4 bytes int), 
         in all 3*16=48 bytes will be allocated */

      q=(int(*)[MAXCOL])malloc(MAXROW*sizeof(*q)); 

      for(i=0; i<MAXROW; i++)
        for(j=0;j<MAXCOL;j++)
          q[i][j]=k++;


      for(i=0;i<MAXROW;i++){
        for(j=0;j<MAXCOL;j++)
          printf(" %2d ", q[i][j]);
        printf("\n");         
      } 
}

#7


0  

#include<stdio.h>

int main(void)
{
    int (*x)[6];                 //pointer to an array of integers
    int y[6] = {11,22,33,44,55,66};    //array of integers
    int *z;                      //pointer to integer
    int i;

    z = y;
    for(i = 0;i<6;i++)
        printf("%d ",z[i]);
    printf("\n");

    x = &y;

    for(int j = 0;j<6;j++)
        printf("%d ",*(x[0]+j));

    return 0;
}

//OUTPUT::

/ /输出:

11 22 33 44 55 66

11 22 33 44 55 66

11 22 33 44 55 66

11 22 33 44 55 66

Pointer to an array are best suitable for multi-dimensional array. but in above example we used single dimension array. so, in the second for loop we should use (x[0]+j) with * to print the value. Here, x[0] means 0th array. And when we try to print value using printf("%d ",x[i]); you will get 1st value is 11 and then some garbage value due to trying to access 1st row of array and so on.

指向数组的指针最适合于多维数组。但是在上面的例子中我们使用了单维数组。因此,在第二个for循环中,我们应该使用(x[0]+j)来打印值。这里,x[0]表示第0个数组。当我们尝试用printf打印值时(“%d”,x[i]);你会得到第一个值是11,然后由于试图访问数组的第一行而得到一些垃圾值,以此类推。

#8


-1  

One should understand the internal representation of (*x)[i]. Internally, it is represented as *((*x)+i), which is nothing but the ith element of the array to which x is pointing. This is also a way to have a pointer pointing to 2d array. The number of rows is irrelevant in a 2d array.

应该理解(*x)[i]的内部表示。在内部,它表示为*((*x)+i),它只是x指向的数组的第i个元素。这也是一个指向二维数组的指针。在2d数组中,行数是不相关的。

For example:

例如:

int arr[][2]={{1,2},{3,4}};
int (*x)(2);
x=arr; /* Now x is a pointer to the 2d array arr.*/

Here x is pointing to a 2d array having 2 integer values in all columns, and array elements are stored contiguously. So (*x)[0] will print arr[0][0] (which is 1), (*x)[1] will print the value of arr[0][1] (which is 2) and so on. (*x+1)[0] will print the value of arr[1][0] (3 in this case) (*x+1)[1] will print the value of arr[1][1] (4 in this case) and so on.

这里x指向一个二维数组,所有列中都有两个整数值,数组元素是连续存储的。所以(*x)[0]打印arr[0][0] (1), (*x)[1]打印arr[0][1](2)的值,以此类推。(*x+1)[0]打印arr[1][0]的值(本例为3)(*x+1)[1]打印arr[1][1]的值(本例为4),以此类推。

Now, a 1d array could be treated as nothing but a 2d array having only one row with as many columns.

现在,一个一维数组可以被当作一个二维数组,它只有一行,列数相同。

int y[6] = {1,2,3,4,5,6};
int (*x)[6];
x =y;

This means x is a pointer to an array having 6 integers. So (*x)[i] which is equivalent to *((*x)+i) will print ith index value of y.

这意味着x是一个指向有6个整数的数组的指针。所以(*x)[i]等于*((*x)+i)将输出y的第i个索引值。

#1


16  

Firstly, your code will not compile. The array has type int[6] (6 elements), while the pointer has type int (*)[5]. You can't make this pointer to point to that array because the types are different.

首先,您的代码不会编译。数组的类型为int[6](6个元素),而指针类型为int(*)[5]。你不能让这个指针指向那个数组,因为类型不同。

Secondly, when you initialize (assign to) such a pointer, you have to use the & on the array: x = &y, not just a plain x = y as in your code.

其次,当您初始化(分配给)这样一个指针时,您必须使用& on数组:x = &y,而不只是在代码中使用简单的x = y。

I assume that you simply typed the code up, instead of copy-pasting the real code.

我假设您只是键入代码,而不是复制粘贴真实的代码。

Thirdly, about the internal representation. Generally, in practice, you should expect all data pointers to use the same internal representation. Moreover, after the above assignments (if written correctly), the pointers will have the same numerical value. The difference between int (*)[5] and int * exists only on the conceptual level, i.e. at the level of the language: the types are different. It has some consequences. For example, if you increment your z it will jump to the next member of the array, but if you increment y, it will jump over the whole array etc. So, these pointers do not really "do the same thing".

第三,关于内部代表性。通常,在实践中,您应该期望所有数据指针都使用相同的内部表示。此外,在上面的赋值之后(如果写得正确的话),指针将具有相同的数值。int(*)[5]和int *之间的差异仅存在于概念层面,即语言层面:类型不同。它有一些后果。例如,如果你增加z它会跳转到数组的下一个元素,但是如果你增加y,它会跳转到整个数组等等,所以这些指针并不是真的“做同样的事情”。

#2


11  

The short answer: There is a difference, but your example is flawed.

简短的回答是:有区别,但是你的例子是有缺陷的。

The long answer:

长回答:

The difference is that int* points to an int type, but int (*x)[6] points to an array of 6 ints. Actually in your example,

不同之处在于int*指向int类型,而int (*x)[6]指向一个6 int的数组。其实在你的例子中,

x = y;

is undefined** behavior, you know these are of two different types, but in C you do what you want. I'll just use a pointer to an array of six ints.

是未定义的**行为,你知道它们有两种不同的类型,但是在C语言中,你想做什么就做什么。我用一个指针指向一个有6个ints的数组。

Take this modified example:

把这个修改后的示例:

int (*x)[6];                 //pointer to an array of integers
int y[6] = {1,2,3,4,5,6};    //array of integers
int *z;                      //pointer to integer
int i;

z = y;
for(i = 0;i<6;i++)
    printf("%d ",z[i]);

x = y; // should be x = &y but leave it for now!

for(i = 0;i<6;i++)
    printf("%d ",x[i]); // note: x[i] not (*x)[i]

First,

首先,

1 2 3 4 5 6

Would be printed. Then, we get to x[0]. x[0] is nothing but an array of 6 ints. An array in C is the address of the first element. So, the address of y would be printed, then the address of the next array in the next iteration. For example, on my machine:

会被打印出来。然后,我们得到x[0]。x[0]只是一个包含6个int的数组。C中的数组是第一个元素的地址。因此,y的地址将被打印出来,然后是下一个迭代中的下一个数组的地址。例如,在我的机器上:

1 2 3 4 5 6 109247792 109247816 109247840 109247864 109247888 109247912

As you can see, the difference between consecutive addresses is nothing but:

正如你所看到的,相邻地址之间的区别就是:

sizeof(int[6]) // 24 on my machine!

In summary, these are two different pointer types.

总之,这是两个不同的指针类型。

** I think it is undefined behavior, please feel free to correct my post if it is wrong.

**我认为这是不明确的行为,如有错误请随时纠正。

#3


4  

Hope this code helps:

希望这段代码可以帮助:

int main() {

    int arr[5] = {4,5,6,7,8};        
    int (*pa)[5] = &arr;
    int *pi = arr;

    for(int i = 0; i< 5; i++) {
        printf("\n%d %d", arr[i], (*pa)[i]);    
    }

    printf("\n0x%x -- 0x%x", pi, pa);
    pi++;
    pa++;
    printf("\n0x%x -- 0x%x", pi, pa);
}

prints the following:

输出如下:

4 4
5 5
6 6
7 7
8 8
0x5fb0be70 -- 0x5fb0be70
0x5fb0be74 -- 0x5fb0be84 

UPDATE: You can notice that pointer to integer incremented by 4 bytes (size of 32 bit integer) whereas pointer to array of integer incremented by 20 bytes (size of int arr[5] i.e. size of 5 int of 32 bit each). This demonstrates the difference.

更新:您可以注意到,指向整数的指针增加了4个字节(32位整数的大小),而指向整数数组的指针增加了20个字节(int arr[5]的大小,即每个32位整数的大小)。这说明不同之处。

#4


3  

To answer your question from the title, from the comp.lang.c FAQ: Since array references decay into pointers, if arr is an array, what's the difference between arr and &arr?

从题目中回答你的问题,从题目中回答。由于数组引用会衰减成指针,如果arr是数组,那么arr和&arr有什么区别呢?

However, the code you've posted has other issues (you're assigning y, not &y to x, and y is a 6-element array, but *x is a 5-element array; both of these should generate compilation warnings).

但是,您发布的代码还有其他问题(您将y赋值,而不是&y赋值给x, y是一个6元素的数组,但*x是一个5元素的数组;两者都应该生成编译警告)。

#5


2  

Who knows - this code exhibits undefined behavior:

谁知道呢?这段代码显示了未定义的行为:

printf("%d ",(*x)[i]);

#6


2  

Hope this code helps.

希望这段代码有帮助。


#include <stdio.h>
#include <stdlib.h>
#define MAXCOL 4
#define MAXROW 3

int main()
{      
      int i,j,k=1;
      int (*q)[MAXCOL];      //pointer to an array of integers

      /* As malloc is type casted to "int(*)[MAXCOL]" and every 
         element (as in *q) is 16 bytes long (I assume 4 bytes int), 
         in all 3*16=48 bytes will be allocated */

      q=(int(*)[MAXCOL])malloc(MAXROW*sizeof(*q)); 

      for(i=0; i<MAXROW; i++)
        for(j=0;j<MAXCOL;j++)
          q[i][j]=k++;


      for(i=0;i<MAXROW;i++){
        for(j=0;j<MAXCOL;j++)
          printf(" %2d ", q[i][j]);
        printf("\n");         
      } 
}

#7


0  

#include<stdio.h>

int main(void)
{
    int (*x)[6];                 //pointer to an array of integers
    int y[6] = {11,22,33,44,55,66};    //array of integers
    int *z;                      //pointer to integer
    int i;

    z = y;
    for(i = 0;i<6;i++)
        printf("%d ",z[i]);
    printf("\n");

    x = &y;

    for(int j = 0;j<6;j++)
        printf("%d ",*(x[0]+j));

    return 0;
}

//OUTPUT::

/ /输出:

11 22 33 44 55 66

11 22 33 44 55 66

11 22 33 44 55 66

11 22 33 44 55 66

Pointer to an array are best suitable for multi-dimensional array. but in above example we used single dimension array. so, in the second for loop we should use (x[0]+j) with * to print the value. Here, x[0] means 0th array. And when we try to print value using printf("%d ",x[i]); you will get 1st value is 11 and then some garbage value due to trying to access 1st row of array and so on.

指向数组的指针最适合于多维数组。但是在上面的例子中我们使用了单维数组。因此,在第二个for循环中,我们应该使用(x[0]+j)来打印值。这里,x[0]表示第0个数组。当我们尝试用printf打印值时(“%d”,x[i]);你会得到第一个值是11,然后由于试图访问数组的第一行而得到一些垃圾值,以此类推。

#8


-1  

One should understand the internal representation of (*x)[i]. Internally, it is represented as *((*x)+i), which is nothing but the ith element of the array to which x is pointing. This is also a way to have a pointer pointing to 2d array. The number of rows is irrelevant in a 2d array.

应该理解(*x)[i]的内部表示。在内部,它表示为*((*x)+i),它只是x指向的数组的第i个元素。这也是一个指向二维数组的指针。在2d数组中,行数是不相关的。

For example:

例如:

int arr[][2]={{1,2},{3,4}};
int (*x)(2);
x=arr; /* Now x is a pointer to the 2d array arr.*/

Here x is pointing to a 2d array having 2 integer values in all columns, and array elements are stored contiguously. So (*x)[0] will print arr[0][0] (which is 1), (*x)[1] will print the value of arr[0][1] (which is 2) and so on. (*x+1)[0] will print the value of arr[1][0] (3 in this case) (*x+1)[1] will print the value of arr[1][1] (4 in this case) and so on.

这里x指向一个二维数组,所有列中都有两个整数值,数组元素是连续存储的。所以(*x)[0]打印arr[0][0] (1), (*x)[1]打印arr[0][1](2)的值,以此类推。(*x+1)[0]打印arr[1][0]的值(本例为3)(*x+1)[1]打印arr[1][1]的值(本例为4),以此类推。

Now, a 1d array could be treated as nothing but a 2d array having only one row with as many columns.

现在,一个一维数组可以被当作一个二维数组,它只有一行,列数相同。

int y[6] = {1,2,3,4,5,6};
int (*x)[6];
x =y;

This means x is a pointer to an array having 6 integers. So (*x)[i] which is equivalent to *((*x)+i) will print ith index value of y.

这意味着x是一个指向有6个整数的数组的指针。所以(*x)[i]等于*((*x)+i)将输出y的第i个索引值。