我是C语言的新手,对*的两种不同用法感到困惑。我知道*的用法称为 dereferencing ,用于检索指针指向的值。
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
我想到的方式是*就像一个运算符,在将它应用于指针时,它在打印语句的上下文中给出值 。
在其他地方,我看到*以下列方式使用:
void someFunction(int **IP){
int *anotherIP = NULL;
*IP = anotherIP;
}
如果我在此处使用相同的思想,则* IP应该是IP指向的值。但这似乎不是用法。而是将本地指针分配给IP指向的指针。
更正:该函数正在将anotherIP
分配给指向IP的指针(即*IP
); IP(指向指针的指针)在传递给函数(**IP
)时被两次取消引用。
我的问题是:*上下文的含义是否相关?如果是,通常应注意哪些上下文?如果没有,我如何理解上面的示例?
此外,在上面的函数中使用双星号的原理是什么?我看到它经常在函数中使用。
谢谢!
答案 0 :(得分:1)
首先,在C语言中,变量的声明应类似于其访问权限。
表示指向int的指针的指针的实际值,即为int的值,因此您可以使用int value = **IP
对其进行访问。
您经常在函数中看到双指针,因为它允许您为返回的值分配空间。
单个指针将按值传递给功能,如果在函数中对其进行更改,则调用者将看不到更改。
答案 1 :(得分:1)
在声明中,一元*
表示所声明的事物具有指针类型:
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
在这些声明之后,以下内容为真:
**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声明语法是基于表达式的类型构建的。假设您有一个名为int
的{{1}}指针,并且想访问该整数值。你会写一个像
p
表达式 x = *p;
的类型为*p
,因此声明表示为
int
如果您有一个名为int *p;
的指向int
的指针数组,并且想访问第p
个元素所指向的整数值,则可以编写
i
同样,表达式 x = *p[i];
的类型为*p[i]
,因此声明写为
int
多个间接显示在两个主要位置:
您要一个函数写入指针类型的参数
请记住,C会按值传递所有函数参数,因此,如果要让函数写入参数,则必须传递指向该参数的指针:
int *p[N];
让我们将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
self 的指针来进行更新。
请记住,如果左值表达式value
的类型为x
,则表达式T
的类型为&x
。同样,将T *
替换为指针类型T
,您将看到表达式P *
的类型为&x
。
您要分配一个锯齿状的数组
有时您需要2D(或3D或更高版本)的类似数组的结构,但您不希望行的大小相同。这样做的通常方法如下:
P **
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
}
}
指向arr
的指针序列中的第一个。
答案 2 :(得分:0)
据我所知,C语言中的星号有3种“用法”。
有乘法:
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 */
看到的带有双星号的是a pointer to a pointer。阅读这些。他们很有趣。