Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C *是否根据其使用的上下文有不同的含义?_C - Fatal编程技术网

C *是否根据其使用的上下文有不同的含义?

C *是否根据其使用的上下文有不同的含义?,c,C,我是C新手,对*的两种不同用法感到困惑。我知道*的用法称为解引用,用于检索指针指向的值 int num = 20; int *ip; ip = # print("This is the pointer's address: %p\n", ip); // bffd8b3c print("This is the value of the pointer: %d\n", *ip); // 20 我的想法是,*就像一个操作符,当它应用于指针时,在print语句的上下文中给出值

我是C新手,对*的两种不同用法感到困惑。我知道*的用法称为解引用,用于检索指针指向的值

int num = 20;
int *ip;
ip = #

print("This is the pointer's address: %p\n", ip);     // bffd8b3c
print("This is the value of the pointer: %d\n", *ip); // 20
我的想法是,*就像一个操作符,当它应用于指针时,在print语句的上下文中给出值

在其他地方,我看到*以以下方式使用:

void someFunction(int **IP){

    int *anotherIP = NULL;
    *IP = anotherIP;

}
如果我在这里使用相同的思想,*IP应该是IP指向的值。但这似乎不是用法。相反,它将本地指针分配给IP指向的指针

更正:函数正在为指向IP的指针分配另一个IP(即
*IP
);IP(指向指针的指针)在传递到函数中时被取消引用两次(
**IP

我的问题是:*的含义是否取决于上下文?如果是,我在常用情况下应该注意哪些上下文?如果没有,我如何理解上面的例子

此外,在上述函数中使用双星号的基本原理是什么?我经常在函数中看到这种用法


谢谢

首先,在C语言中,变量的声明应该与它的访问类似。 表示指向int的指针的实际值,它是int值,因此您可以使用
int-value=**IP
访问它

您经常在函数中看到双指针,因为它允许您为返回的值分配空间


一个指针将通过值传递给funktion,如果在函数中更改它,调用者将看不到更改

据我所知,星号在C语言中有三种“用法”

这里有乘法:

int result = 3 * 3; /* result == 9 */
有一个定义:

int *pointer_to_result = &result; /* define a pointer to an int, and initialize it with the address of the result variable */
最后,对于解引用:

int copy_of_result = *pointer_to_result /* copy_of_result == 9 */
您看到的双星号是。仔细阅读这些。它们非常有趣。

在声明中,一元
*
表示声明的对象具有指针类型:

T *p;       // p has type "pointer to T"
T *p[N];    // p has type "array of pointer to T"
T (*p)[N];  // p has type "pointer to array of T"
T *p();     // p has type "function returning pointer to T"
T (*p)();   // p has type "pointer to function returning T"
下标
[]
和函数调用
()
运算符的优先级高于一元
*
,因此像
*p[i]
这样的表达式将被解析为
*(p[i])
;您正在取消对
p[i]
的结果的引用。如果
p
是指向某个数组的指针,那么您必须编写
(*p)[i]
-您需要取消引用
p
,然后将其下标到结果中

您可以有多个级别的间接寻址:

T **p;           // p has type "pointer to pointer to T"
T ***p;          // p has type "pointer to pointer to pointer to T"
T *(*p)[N];      // p has type "pointer to array of pointer to T"
T *(*(*p)())[N]; // p is a pointer to a function returning a pointer
                 // to an N-element array of pointer to T
int x = 10;    
int *p = &x;    // p stores the address of x
int **pp = &p;  // pp stores the address of p
在表达式中,一元
*
运算符取消对指针的引用以访问指向的对象,如您的示例所示。同样,您可以有多个级别的间接寻址:

T **p;           // p has type "pointer to pointer to T"
T ***p;          // p has type "pointer to pointer to pointer to T"
T *(*p)[N];      // p has type "pointer to array of pointer to T"
T *(*(*p)())[N]; // p is a pointer to a function returning a pointer
                 // to an N-element array of pointer to T
int x = 10;    
int *p = &x;    // p stores the address of x
int **pp = &p;  // pp stores the address of p
在这些声明之后,以下是正确的:

**pp == *p ==  x == 10 // all of these expressions have type int
 *pp ==  p == &x       // all of these expressions have type int *
  pp == &p             // all of these expressions have type int **
 &pp                   // this expression has type int ***
C声明语法是基于表达式类型构建的。假设您有一个指向名为
p
int
的指针,并且希望访问该整数值。你会写一个这样的表达

x = *p;
表达式
*p
的类型是
int
,因此声明写为

int *p;
int *p[N];
如果您有一个名为
p
的指向
int
的指针数组,并且希望访问第
i
元素所指向的整数值,那么您可以编写

x = *p[i];
同样,表达式
*p[i]
的类型是
int
,因此声明写为

int *p;
int *p[N];
多个间接寻址显示在两个主要位置:

您希望函数写入指针类型的参数

请记住,C按值传递所有函数参数,因此如果希望函数写入参数,则必须传递指向该参数的指针:

void foo( T *ptr )
{
  *ptr = new_value();  // writes a new value to the thing ptr points to
}

void bar( void )
{
  T value;
  foo ( &value );     // writes a new value to value
}
让我们将
T
替换为指针类型
p*

void foo( P **ptr )
{
  *ptr = new_value();  // writes a new value to the thing ptr points to
}

void bar( void )
{
  P *value;
  foo ( &value );     // writes a new value to value
}
正如你所看到的,它的工作原理是一样的。我们想更新
值的内容,所以必须传递一个指向它的指针。是的,
value
已经有一个指针类型,但是我们需要一个指向
value
本身的指针来更新它

请记住,如果左值表达式
x
的类型为
T
,则表达式
&x
的类型为
T*
。同样,将
T
替换为指针类型
P*
,您将看到表达式
&x
具有类型
P**

您想分配一个锯齿状数组

有时,您需要一个2D(或3D,或更高)的类似阵列的结构,但不希望行的大小相同。通常的做法如下:

T **arr = malloc( N * sizeof *arr ); // allocate an array to hold N objects of type T *

if ( arr )
{
  for ( size_t i = 0; i < N; i++ )
  {
    arr[i] = malloc( M * sizeof *arr[i] ); // allocate an array to hold M objects of type T, where M can vary from row to row
  }
}
T**arr=malloc(N*sizeof*arr);//分配一个数组以容纳N个T类型的对象*
如果(arr)
{
对于(大小i=0;i

arr
指向指向
T
的指针序列中的第一个

是的,当它用于乘法时,它有两种含义。当用作类型的一部分时,它使该类型成为指向基类型的指针。当与值一起使用时,它将取消对指针的引用。@ThomasJager感谢您的回复。您提到的两个含义如何适用于函数中的*IP示例?我不知道它是如何定义类型或取消引用的。
IP
是指向
int
的指针。因此,
*IP
是指向
int
的指针,就像
另一个IP
一样。而
**IP
*IP
指向的
int
。因此,说“它是将一个本地指针分配给**IP指向的指针”是不正确的。我发现,通过将
int**IP
这样的声明视为
**IP
被声明为
int
来调和这两种“含义”是有用的(也就是说,如果你两次遵从
IP
,你会得到一个
int
),这意味着
*IP
指向t