读取C指针类型声明

读取C指针类型声明,c,pointers,types,C,Pointers,Types,我是C语言编程新手。有人能给我解释一下如何“阅读”像*(float*)a这样的声明,并一步一步地给出一些例子吗 谢谢 通常,您必须同时考虑运算符的优先级和关联性: 在这种情况下,取消引用操作符和强制转换操作符具有相同的优先级,并且都是从右到左的关联。这意味着每个操作符应用于其右侧的内容,并且由于它们具有相同的优先级,因此解引用操作符在其右侧的强制转换操作符之后应用 因此,执行的操作顺序是:访问->将其转换为(float*)->取消引用它 编辑:如果有一元运算符(取消引用、强制转换、求反等),则该

我是C语言编程新手。有人能给我解释一下如何“阅读”像
*(float*)a这样的声明,并一步一步地给出一些例子吗


谢谢

通常,您必须同时考虑运算符的优先级和关联性:

在这种情况下,取消引用操作符和强制转换操作符具有相同的优先级,并且都是从右到左的关联。这意味着每个操作符应用于其右侧的内容,并且由于它们具有相同的优先级,因此解引用操作符在其右侧的强制转换操作符之后应用

因此,执行的操作顺序是:访问->将其转换为(float*)->取消引用它

编辑:如果有一元运算符(取消引用、强制转换、求反等),则该运算符始终是从右向左关联的,并且在计算其右侧的所有表达式后应用。因此,在我们的例子中,您可以说运算符也是从右向左应用的,而无需查看上表。

*(float*)a
不是声明;这是一个演员的表情。在这种特殊情况下,它取
a
的值,将其视为指向
float
的指针,并取消对结果的引用。很可能
a
是指向不同类型的指针,我们希望将其视为指向
float
的指针

就指针声明而言

一个简单的指针声明如下所示

T *p;  // p is a pointer to T
其中,
T
是任何类型(可能带有限定符,如
const
volatile
)。对象
p
的类型是“指向
T
”的指针;类型完全由
T
中的类型说明符和限定符以及声明符
*p
组合指定

声明器引入被声明对象的名称,以及类型说明符中未提供的任何类型信息。在上面的声明中,
*p
是声明者。它提供对象的名称(
p
)和任何其他类型信息(指向的指针)。请注意,即使您将声明写为

T* p;
它将被解析为

数组和函数的声明也是如此:

T a[N]; // a is an N-element array of T
T f();  // f is a function returning T
a
的数组属性由声明器
a[N]
给出,而
f
的函数属性由声明器
f()
给出

您可以将
*
[]
()
组合,如下所示:

T *a[N];   // a is an N-element of pointers to T
T (*a)[N]; // a is a pointer to an N-element array of T
T *f();    // f is a function returning pointer to T
T (*f)();  // f is a pointer to a function returning T
在声明和表达式中,一元
*
的优先级低于后缀
[]
()
,因此
*a[N]
*f()
被解析为
*(a[N])
*(f())
。如果希望
a
成为指向数组的指针而不是指针数组,则必须将
*
a
显式分组为
(*a)[N]

您可以进一步组合这些元素,如下所示:

T **p;       // p is a pointer to a pointer to T
T a[N][M];   // a is an NxM array of T
T (*f[N])(); // f is an array of pointers to functions returning T
T (*f())[N]; // f is a function returning a pointer to an array of T
T *(*(*a[N])())(); // a is an array of pointers to functions returning pointers to functions returning pointers to T
是的,函数可以返回指向数组的指针和指向其他函数的指针,是的,语法看起来很奇怪,但是如果从逻辑上遵循声明器的工作方式。您只需将函数调用(以及任何参数)替换为指针名称:

T (*a)[N] => T (*f())[N], a => f()
T (*f)()  => T (*g())(),  f => g()
下面是一个示例:C标准库中的
信号
函数。它是一个返回指向另一个函数的指针的函数:

void (*signal(int sig, void (*func)(int)))(int);
要阅读此声明,请从最左边的标识符开始,应用上面给出的优先规则,找到解决方法。将这些规则递归应用于任何函数参数:

       signal                                      -- signal
       signal(                          )          -- is a function taking
       signal(    sig                   )          --   parameter sig
       signal(int sig                   )          --   is an int
       signal(int sig,        func      )          --   parameter func
       signal(int sig,      (*func)     )          --   is a pointer
       signal(int sig,      (*func)(   ))          --   to a function taking
       signal(int sig,      (*func)(   ))          --     unnamed parameter
       signal(int sig,      (*func)(int))          --     is an int
       signal(int sig, void (*func)(int))          --   returning void
      *signal(int sig, void (*func)(int))          -- returning a pointer
     (*signal(int sig, void (*func)(int)))(   )    -- to a function taking
     (*signal(int sig, void (*func)(int)))(   )    --   unnamed parameter
     (*signal(int sig, void (*func)(int)))(int)    --   is an int  
void (*signal(int sig, void (*func)(int)))(int);   -- returning void

因此,
signal
是一个返回函数指针的函数
signal
接受两个参数,一个是普通的
int
,另一个是指向接受
int
并返回void的函数的指针。注意,在函数声明中,不必指定参数名。它们需要在相应的函数定义中指定

这不是一个声明。它将取消引用一个变量
a
强制转换为指向
float
@EugeneSh的指针。请多解释!谢谢:)假设您正在编写
qsort
所需的
cmp
函数,该函数有两个
void*
参数,则该函数可能重复。您知道它们实际上指向
float
所以
如果(*(float*)a>*(float*)b)返回1用于铸造正确的数据类型.@ RCB——这是关于C++的。我不确定这里的优先级是相关的。左边的代码> */C>可以应用到(语法上)是<代码>(浮点*)< < /代码>的结果。谢谢!戴维德·维森丁
(int*)->(float*)
也许吧。@OliverCharlesworth你是对的。无论如何,这是一个通用的算法,可以用来理解任何表达式。无论如何,我在答案中加了一个注释。Thanks@sjsam是的,现在我已经修好了。谢谢。例如:(float*)xfunction(x,y,z)是什么@约翰Bode@M_sansa-这是一个函数调用,返回值被转换为指向
float
的指针。
       signal                                      -- signal
       signal(                          )          -- is a function taking
       signal(    sig                   )          --   parameter sig
       signal(int sig                   )          --   is an int
       signal(int sig,        func      )          --   parameter func
       signal(int sig,      (*func)     )          --   is a pointer
       signal(int sig,      (*func)(   ))          --   to a function taking
       signal(int sig,      (*func)(   ))          --     unnamed parameter
       signal(int sig,      (*func)(int))          --     is an int
       signal(int sig, void (*func)(int))          --   returning void
      *signal(int sig, void (*func)(int))          -- returning a pointer
     (*signal(int sig, void (*func)(int)))(   )    -- to a function taking
     (*signal(int sig, void (*func)(int)))(   )    --   unnamed parameter
     (*signal(int sig, void (*func)(int)))(int)    --   is an int  
void (*signal(int sig, void (*func)(int)))(int);   -- returning void