【问题标题】:typedef - Typedef without curly bracestypedef - 没有花括号的 Typedef
【发布时间】:2020-08-11 20:29:19
【问题描述】:

我是 C 的新手,但是这个语法是什么意思?

typedef Value (*NativeFn)(int argCount, Value* args);

据我了解,这里使用“值”来定义新名称的类型。 看不懂的部分是(*NativeFn)(int argCount, Value* args);,这部分是什么意思?

【问题讨论】:

  • 这是一个函数指针,您可能需要进一步研究它。大括号与它有什么关系?
  • 这是一个指向函数的指针阅读here了解更多详情。
  • 可能重复:Typedef function pointer?.
  • NativeFn 在此处定义(Value msu 之前已定义)。它是“指向函数的指针,接受一个 int 和一个指向值的指针并返回一个值”的类型别名。
  • 你可能对花括号感到困惑,因为很多类型定义都是针对结构类型的。大括号是 struct 定义语法的一部分,而不是 typedef 语法的一部分。

标签: c function-pointers typedef


【解决方案1】:

其他人说得对:

typedef Value (*NativeFn)(int argCount, Value* args);

为指向函数的类型创建一个 typedef 名称 NativeFn

typedef 的语法与一般 C 声明的语法一样,可能会令人困惑。 typedef 特性实际上是在声明语法建立之后添加到语言中的,并且必须在不破坏其他任何内容的情况下添加它。解决方案是在语法上将typedef 视为存储类说明符(尽管它在语义上不是一个)。除了typedef 之外的存储类说明符是externstatic_Thread_localautoregister

这意味着您可以通过将关键字typedef 替换为static 来理解typedef 声明。在static 声明声明某种类型的对象(或函数)时,相应的typedef 声明创建具有相同名称和类型的类型定义。所以这个:

static int foo;

创建int 类型的对象foo(具有静态存储持续时间),同时:

typedef int foo;

创建一个类型名称 foo,它是类型 int 的别名。

如果你的声明是:

static Value (*NativeFn)(int argCount, Value* args);

它会将NativeFn 定义为指向函数对象的指针(函数返回Value 类型的结果)。将static 替换为typedef 意味着NativeFn 是一个类型名称,它引用了相同的指向函数的类型。

记住typedef 不会创建新类型也很重要。它为现有类型创建一个新名称。

【讨论】:

    【解决方案2】:

    考虑这样的记录

    Value (int argCount, Value* args)
    

    它表示一个函数类型,它具有返回类型Value 和两个intValue * 类型的参数。

    标识符 Value 在其他地方声明,例如可以是类型的别名。

    要为函数类型引入指针类型的别名,您可以编写

    typedef Value (*NativeFn)(int argCount, Value* args);
    

    所以如果你有一个函数例如

    Value some_function(int argCount, Value* args);
    

    那么你可以使用 typedef 别名定义来声明一个指向这个函数的指针,方法如下

    NativeFn pointer_to_some_function = some_function; 
    

    【讨论】:

      【解决方案3】:

      typedef 工具用于为类型创建别名。例如,

      typedef int *iptr;
      

      创建名称 iptr 作为类型 int * 的同义词,因此您可以使用声明指针

      iptr p, q;
      

      而不是写

      int *p, *q;
      

      C 声明语法比大多数人意识到的要复杂一些,尤其是在涉及指针的地方。基本规则是:

      T *p;            // p is a pointer to T
      T *a[N];         // a is an array of pointer to T
      T *f();          // f is a function returning pointer to T
      T (*a)[N];       // a is a pointer to an array of T
      T (*f)();        // f is a pointer to a function returning T
      T const *p;      // p is a pointer to const T
      const T *p;      // same as above
      T * const p;     // p is a const pointer to T
      

      事情可以变得任意复杂——你可以拥有指向函数的指针数组:

      T (*a[N])();
      

      或返回数组指针的函数:

      T (*f())[N];
      

      甚至更严重的暴行。当混合有参数时,函数指针声明会变得更加丑陋;幸运的是,您只需要在声明中列出参数 types,而不是名称:

      typedef Value (*NativeFn)(int, Value*);
      

      让事情变得一点更容易理解。

      该声明创建了NativeFn 作为类型“指向采用intValue * 并返回Value 的函数的指针”的同义词。

      假设你有一个定义为的函数

      Value foo( int argcCount, Value *args )
      {
        Value result;
        ...
        return result;
      }
      

      如果你想创建一个指向这个名为fptr的函数的指针,你通常会将它声明为

      Value (*fptr)(int, Value *) = foo;
      

      但是,上面的typedef 声明允许您编写

      NativeFn fptr = foo;
      

      说了这么多,使用typedef 谨慎。问题在于,虽然它可以创建一种更易于阅读的方式来声明某些项目,但它也隐藏了一些潜在有用的信息。例如,尽管上面有 iptr 示例,但最好隐藏 typedef 后面的指针 - 如果有人需要在 pq 上使用一元 * 运算符以便使用它们是正确的,而不是这些信息需要在这些项目的声明中。如果有人需要调用 fptr 指向的东西,那么他们需要知道返回类型是什么、参数的数量和类型等,但是所有这些信息都在使用 typedef 名称的声明。

      【讨论】:

        【解决方案4】:

        嗯,

        typedef (*NativeFn)(int argCount, Value* args)
        

        意思

        NativeFn 是一个 function type(can also be called "a pointer to function" or "function pointer"),它返回 Value 并将 intValue * 作为参数。

        如果您不知道为什么以及如何使用它,请阅读下面的代码,尤其是 cmets,您会很清楚 (*NativeFn)(int argCount, Value* args) 的含义以及如何使用它:

        #include <stdio.h>
        
        // note: "Value" is a type declared earlier
        //       for discussions sake we're declaring our own Value type
        
        typedef struct __value {
            int x, y;
        } Value;
        
        
        // now, the following tells us that:
        // "NativeFn" is some function type that returns "Value"
        typedef Value (*NativeFn)(int argCount, Value* args);
        
        
        // okay, see how to use "NativeFn"
        // for use "NativeFn" we've to declare some function first
        // which takes two arguments same as "NativeFn" and return "Value"
        Value someFun(int argCount, Value* args) {
            // do something argCount and args
            // at last it should return some "Value" type
            Value v = {2, 3};
            return v;
        }
        
        int main() {
            // now its time to use "NativeFn"
            NativeFn fun;
        
            fun = someFun; // notice we can use fun as a variable and assign a
            // function to it, which must take arguments same as "NativeFn" and returns "Value" type
        
            Value input = {10, 12};
            
            Value output = fun(1, &input); // note, we're calling "fun", not "someFun"
        
            // it'll output 2, 3, cause we're returning Value v = {2, 3} from "someFun"
            printf("(x, y): %d, %d\n", output.x, output.y);
            
            return 0;
        }
        

        如果你有任何问题,请在评论中问我...

        【讨论】:

          猜你喜欢
          • 2012-03-19
          • 2012-01-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多