函数声明中不熟悉的C语法

时间:2018-11-17 23:10:41

标签: c function

当前正在查看一些对我没有任何意义的C代码。什么是(elementSize)?应该如何将参数传递给此静态函数?这种语法样式的名称是什么,以便我可以进一步了解它?

static int torch_Tensor_(elementSize)(lua_State *L)
{
  luaT_pushinteger(L, THStorage_(elementSize)());
  return 1;
}

https://github.com/torch/torch7/blob/master/generic/Tensor.c

这是我要理解的文件,以供参考。

1 个答案:

答案 0 :(得分:4)

通常

static int torch_Tensor_(elementSize)(lua_State *L)

意味着torch_Tensor_是一个函数,该函数带有一个没有类型(?!-语法错误)的名为elementSize的单个参数,并返回一个带有指向lua_State的指针的函数,并且返回int。这显然是无效的(函数不能返回其他函数)。

但是实际上,torch_Tensor_被定义为类似于函数的宏,因此在编译器甚至没有看到此声明之前,torch_Tensor_(elementSize)都会被其他内容代替。

https://github.com/torch/torch7/blob/master/Tensor.c中有

#include "general.h"

#define torch_Storage_(NAME) TH_CONCAT_4(torch_,Real,Storage_,NAME)
#define torch_Storage TH_CONCAT_STRING_3(torch.,Real,Storage)
#define torch_Tensor_(NAME) TH_CONCAT_4(torch_,Real,Tensor_,NAME)
#define torch_Tensor TH_CONCAT_STRING_3(torch.,Real,Tensor)

#include "generic/Tensor.c"
#include "THGenerateAllTypes.h"

#include "generic/Tensor.c"
#include "THGenerateHalfType.h"

TH_CONCAT_...中定义了lib/TH/THGeneral.h.in

#define TH_CONCAT_STRING_3(x,y,z) TH_CONCAT_STRING_3_EXPAND(x,y,z)
#define TH_CONCAT_STRING_3_EXPAND(x,y,z) #x #y #z

#define TH_CONCAT_4_EXPAND(x,y,z,w) x ## y ## z ## w
#define TH_CONCAT_4(x,y,z,w) TH_CONCAT_4_EXPAND(x,y,z,w)

因此,将torch_Tensor_定义为包含generic/Tensor.c之前的宏。

torch_Tensor_(elementSize)

扩展到

TH_CONCAT_4(torch_,Real,Tensor_,elementSize)

扩展为

TH_CONCAT_4_EXPAND(torch_,...,Tensor_,elementSize)

...是一个占位符,不是真实代码。 Real在各种THGenerate*Type.h文件中被定义为宏,因此该行实际上变为

TH_CONCAT_4_EXPAND(torch_,char,Tensor_,elementSize)
TH_CONCAT_4_EXPAND(torch_,int,Tensor_,elementSize)
TH_CONCAT_4_EXPAND(torch_,float,Tensor_,elementSize)
...

取决于上下文。无论如何,最终结果是表单的单个标识符

torch_charTensor_elementSize
torch_intTensor_elementSize
torch_floatTensor_elementSize
...

(一个令牌)。

由此产生的函数定义看起来像例如

static int torch_charTensor_elementSize(lua_State *L)
{
    ...
}

取决于其中包含generic/Tensor.c的上下文。

以这种方式完成操作的原因是,对于多个不同的类型,它们具有等同于相同代码的代码。在C ++中,您将编写一个函数模板:

namespace torch {
    template<typename Real>
    static int Tensor_elementSize(lua_State *L) { ... }
}

但是C没有模板(也没有名称空间),因此,获取此类“通用”代码的唯一方法是使用宏和预处理技巧(以及手动“修饰”名称;例如elementSize浮点数的函数实际上称为torch_floatTensor_elementSize)。

我们真正想做的就是抽象一个类型参数,这里称为Real