*ptr[10]和(*ptr)[10]的区别

17

以下是代码:

    int (*ptr)[10];
    int a[10]={99,1,2,3,4,5,6,7,8,9};
    ptr=&a;
    printf("%d",(*ptr)[1]);

它应该输出什么?我期望看到的是垃圾值,但实际输出为1
(因此我得出结论,以这种方式初始化指针数组ptr[10]将按顺序指向a[10]中的元素)。

但那么这段代码呢:

int *ptr[10];
int a[10]={0,1,2,3,4,5,6,7,8,9};
*ptr=a;
printf("%d",*ptr[1]);

它正在发生分段错误。


1
这可能对你有所帮助:[https://dev59.com/wGcs5IYBdhLWcg3wp1v3#12674708] - Grijesh Chauhan
写“between”和“output”完全是那么难吗? - Eregrith
@GrijeshChauhan:Thanks..!! - Amit Gupta
6个回答

20

int *ptr[10];

这是一个包含10个int*指针的数组,不是像您所想象的指向10个int的数组的指针。

int (*ptr)[10];

这是一个指向包含10个int的数组的指针。

我认为这与int *ptr;是相同的,因为两者都可以指向一个数组,但是给定的形式只能指向一个包含10个int的数组。


11
int (*ptr)[10];

是一个指向包含10个整数的数组的指针。

int *ptr[10];

这是一个由10个指针组成的数组。

segfault原因:

*ptr=a; printf("%d",*ptr[1]);

在这里,你将数组a的地址赋给了ptr,它会指向元素a[0]。这等同于:*ptr=&a[0];

然而,当你使用ptr[1]进行打印时,你访问的是未初始化的指针,其行为未定义,因此导致了segfault。


4

int(*)[10] 是指向一个包含10个元素的整型数组的指针。也就是说,它指向 int a[10]

int *[10] 则是一个整型指针的数组。

#include <stdio.h>
int main()
{

int *ptr[10];
int a[10]={0,1,2,3,4,5,6,7,8,9};

printf("\n%p  %p", ptr[0], a);

*ptr=a; //ptr[0] is assigned with address of array a.

printf("\n%p  %p", ptr[0], a); //gives you same address

printf("\n%d",*ptr[0]); //Prints zero. If *ptr[1] is given then *(ptr + 1) i.e ptr[1] is considered which is uninitialized one.

return 0;
}

1

int (*p)[10] 表示 p 现在是一个指向大小为 10 的整数数组的指针。

int *p[10] 表示 p 是一个包含 10 个整数指针的数组。


1

int (*p)[10]是指向一个有10个整数的数组的指针,每行可以有任意数量的行。它基本上可用于指向二维数组,并且可以通过增加 i 来访问 *(p+i)[10],其与 a[i][10] 相同,这里的 'i=1,2,3...' 可以访问 1,2,3.. 行

int *p[10] 是一个包含10个整数指针的数组。

如果数组是二维的,例如

b[2][10]={{0,1,2,3,4,5,6,7,8,9},{10,11,12,13,14,15,16,17,18,19}};

基本上,(*ptr)[10](其中高维度索引被省略,即2)可以用作指向数组的二维指针(每行包含10个元素,即第一维),如(*ptr)[10]=&b

在提供的printf("%d",(*ptr)[1]);中,(*ptr)*(ptr+0)相同,计算出第一维即b[0][0]的值为0。同样地,要访问数组的第二维b[1][0],表达式将是**(ptr+1)*(ptr+1)[0]*(*(ptr+i)+j); //其中i=1且j=0给出第二维的第一个元素即10。

我回答得很长,以便易于理解。


0

(*ptr)[10]的唯二用途是:

  • 处理二维数组
  • typedef 固定长度数组

由于第一个用例已经由Sree harsha Punyasamudram解释过, 我将解释更为特殊的用例。

    #include <stdio.h>

typedef int arr1d10[10];
typedef int arr2d3[3][3];

void test1d0(arr1d10 *arr)
{
    /* This is the same as the case with function test1d1(). */
    printf("Element: %d\n", (*arr)[0]);
}

void test1d1(int (*arr)[10])
{
    /* As arr is a pointer to an array of 10 integers, pointer arithmetic will work with the size of an array of 10 integers, i.e. 
       when you increment arr it will increment by sizeof(arr1d10), which is 40 bytes.
       That's why when you dereference it, you can't simply do arr[1], because it will increment arr by 40 bytes forward.
       Also when dereferencing it, because it thinks it points to a whole array it will give you that array - it's address.
       This is another reason you can't do just arr[i], because those will be just addresses.
       The correct way is to dereference it once(*arr)), to get the address (think of implicitely casting to int*) and then you can do as usually (*arr)[1]).
    */
    printf("Element: %d\n", (*arr)[1]);
}

void test2d0(arr2d3 *arr2d)
{
    /* This is a little more complicated, but the principle is the same as above. */
    printf("Element: %d\n", (*arr2d)[0][0]);
}

void test2d1(int (*arr2d)[3][3])
{
    printf("Element: %d\n", (*arr2d)[0][1]);
}

int main(void)
{
    arr1d10 arr1d = {0, 1, 2};
    arr2d3 arr2d = { {0,1},{2,3},{3,4}};
    int (*p1d)[10] = &arr1d; 
    int (*p2d)[3][3] = &arr2d;

    printf("********** PRINT 1D array **********\n");
    test1d0(&arr1d);
    test1d1(&arr1d);
    test1d0(p1d);
    test1d1(p1d);

    printf("********** PRINT 2D array **********\n");
    test2d0(&arr2d);
    test2d1(&arr2d);
    test2d0(p2d);
    test2d1(p2d);

    return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接