【问题标题】:What is the difference between *p and (*p)[3] in the function?函数中的 *p 和 (*p)[3] 有什么区别?
【发布时间】:2023-03-04 22:28:01
【问题描述】:

我是 C 中数组编程和学习指针的新手。看看下面的程序。

第一期节目

  #include<stdio.h>
  int fun();
  int main()
  {
   int num[3][3]={21,325,524,52,0,6514,61,33,85};
   fun(num);
   printf("%d",*(*(num+1)+1));
   *(*(num+1)+1)=0;
   printf("%d",*(*(num+1)+1));
   return 0;
   }
   int fun(int **p)
   {
    *(*(p+1)+1)=2135;
    return 0;
     }

第二个节目

   #include<stdio.h>
  int fun();
  int main()
  {
   int num[3][3]={21,325,524,52,0,6514,61,33,85};
   fun(num);
   printf("%d",*(*(num+1)+1));
   *(*(num+1)+1)=0;
   printf("%d",*(*(num+1)+1));
   return 0;
   }
   int fun(int *p)
   {
    *((p+1)+1)=2135;
    return 0;
   }

第三期节目

     #include<stdio.h>
  int fun();
  int main()
  {
   int num[3][3]={21,325,524,52,0,6514,61,33,85};
   fun(num);
   printf("%d",*(*(num+1)+1));
   *(*(num+1)+1)=0;
   printf("%d",*(*(num+1)+1));
   return 0;
   }
   int fun(int (*p)[3])
   {
    *(*(p+1)+1)=2135;
    return 0;
     }
  1. 在第一个程序中**p 用于fun() 函数,我认为它应该是正确的,并且在该函数中我编写了*(*(p+1)+1) 来更改第一个数组的第一个元素。但是在编译这个程序时它显示error: invalid type argument of unary '*' (have 'int')。据我所知,num 是一个指向数组的指针,它保存着num[1] 的地址,它又保存着num[1][0] 的地址。
  2. 在编译第二个程序时,编译器没有显示错误。 *((p+1)+1)=0 正在改变第一个数组的第二个元素的值。为什么它改变第零个数组的第二个元素的值而不是第一个数组的第一个元素的值?如何?应该是*(*(p+1)+1)=0
  3. 在第三个程序中,编译器没有显示错误,并且显示了正确的结果。如何?。 *(p)[3] 是什么意思?

我已经搜索过,但没有找到满意的结果。

【问题讨论】:

  • 请删除所有出现的“+0”,然后删除所有不必要的大括号。它们没有用,会引起严重的头痛。
  • 数组名是指向数组第一个元素的指针。也许在内部它并不完全相同,但您可以将其用作指针。
  • 我已经编辑了这个问题。 :)
  • int *(p)[3]int *p[3] 相同,但与int (*p)[3] 不同。你可能是指后者
  • @MattMcNabb 我已经编辑了这个问题。 :) 顺便说一句,感谢您的回复。

标签: c function pointers function-pointers memory-address


【解决方案1】:

我想你在问:有什么区别

int fun(int *p)

int fun(int (*p)[3])

第一个需要一个指向int 的指针。第二个需要一个指向 3 个ints 数组的指针。

您可以使用num 调用这两个函数,因为您将函数声明为

int fun();

如果您像定义的那样声明函数,您将收到第一个版本的编译器错误/警告。

这是代码的更新版本和生成的编译器警告,使用 gcc 和编译器标志 -Wall

#include <stdio.h>

int fun(int *p);

int main()
{
   int num[3][3]={21,325,524,52,0,6514,61,33,85};
   fun(num);
   return 0;
}

int fun(int *p)
{
   *(p+0)=2135;
   return 0;
}
test.c: In function ‘main’:
test.c:7:4: warning: missing braces around initializer [-Wmissing-braces]
test.c:7:4: warning: (near initialization for ‘num[0]’) [-Wmissing-braces]
test.c:8:4: warning: passing argument 1 of ‘fun’ from incompatible pointer type [enabled by default]
test.c:3:5: note: expected ‘int *’ but argument is of type ‘int (*)[3]’

【讨论】:

  • 感谢您的回答。 :) 但是如果我在函数中写 **p 呢?
  • @user3788135,您可以将**p 用于第二个版本,但不能用于第一个版本。在第一个版本中,*p 的类型为 int**p 不是有效类型。
  • 对不起,先生,我没有得到您想要解释的内容。我想说的是,如果 num 是指向数组的指针,那么我们可以不写 **p 吗?
  • @user3788135,在fun 中,不知道在调用函数中如何定义num。它只能使用参数p。如果p 定义为int *p,则**p 不是有效类型。
  • 谢谢您的回复先生。先生您能解释一下指针指针和数组指针之间的区别吗。因为它真的有助于我理解这一点。
【解决方案2】:

你所有的程序都是格式错误的。您的编译器必须产生警告或错误消息,并且产生的任何可执行文件的输出都是没有意义的。

它们的格式不正确,因为 int[3][3]int **int *int *[3] 不兼容。

要将int[3][3] 传递给函数,该函数必须接受int (*)[3] 而不能接受其他任何内容(当然,void * 除外)。

这是因为数组可以转换为指向数组第一个元素的指针。 (在 C 语法中,num 可以用来表示&amp;num[0])。

在 C 中,只有真正的一维数组; int[3][3] 类型的数组被认为是一个由 3 个元素组成的数组,每个元素是一个由 3 个整数组成的数组。

所以指向num的第一个元素的指针是指向3个整数数组的指针,写成int (*p)[3]。你可以写:

int (*p)[3] = &num[0];

或同一事物的简写:

int (*p)[3] = num;

注意。你不断地写*(*(num+1)+1)),这很难阅读。而不是这个,num[1][1] 似乎更清晰。

在 C 中,x[y] 始终完全等同于 *(x+y)

【讨论】:

  • 我知道我可以做到,但是因为我正在学习指针,所以我想在指针中编写所有代码
猜你喜欢
  • 2019-12-14
  • 1970-01-01
  • 2013-08-14
  • 2022-12-04
  • 1970-01-01
  • 2013-12-10
  • 1970-01-01
  • 1970-01-01
  • 2019-11-06
相关资源
最近更新 更多