读取C指针类型强制转换



我是C语言编程的新手。有人能给我解释一下如何";读取";像*(float *)a这样的声明,并逐步给出一些示例。

谢谢!

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

就指针声明而言。。。

一个简单的指针声明看起来像

T *p;  // p is a pointer to T

其中CCD_ 7是任何类型(可能具有类似constvolatile的限定符(。对象p的类型为"指向T的指针";类型完全由CCD_ 12中的类型说明符和限定符以及声明符CCD_。

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

T* p;

它将被解析为

T (*p);

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

T a[N]; // a is an N-element array of T
T f();  // f is a function returning T

a的数组ness由声明器a[N]给出,f的函数ness由声明符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标准库的signal函数。这是一个返回指向另一个函数的指针的函数:

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的函数的指针。请注意,在函数声明中,不必指定参数名称。它们需要在相应的函数定义中指定。

通常,您必须关心运算符的优先级和关联性:table

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

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

EDIT:如果你有一个一元运算符(解引用、强制转换、求反等(,该运算符总是从右到左关联的,它在计算完右侧的所有表达式后应用。因此,在我们的情况下,您可以说运算符也是从右向左应用的,而无需查看上表。

最新更新