我正在尝试编译下面找到的这段代码。 但是,我在iteminfo_fields,weaponinfo_fields和projectileinfo_fields定义的每一行都有一个错误,说“初始化值必须是常量表达式。”,除了每个“{NULL,0,0}”的最后一行 我猜这是来自ITEMINFO_OFS(),WEAPON_OFS(),PROJECTILE_OFS()。
我想了解这三行:
#define WEAPON_OFS(x) (size_t)&(((weaponinfo_t *)0)->x) #define PROJECTILE_OFS(x) (size_t)&(((projectileinfo_t *)0)->x) #define ITEMINFO_OFS(x) (size_t)&(((iteminfo_t *)0)->x)
但是,我真的无法理解它们是如何工作的...... 我需要帮助解剖它们。任何人都可以阅读它们并以更简单的形式重写它们吗?
#define WEAPON_OFS(x) (size_t)&(((weaponinfo_t *)0)->x) #define PROJECTILE_OFS(x) (size_t)&(((projectileinfo_t *)0)->x) #define ITEMINFO_OFS(x) (size_t)&(((iteminfo_t *)0)->x) fielddef_t iteminfo_fields[] = { {"name", ITEMINFO_OFS(name), FT_STRING}, {"model", ITEMINFO_OFS(model), FT_STRING}, {"modelindex", ITEMINFO_OFS(modelindex), FT_INT}, {"type", ITEMINFO_OFS(type), FT_INT}, {"index", ITEMINFO_OFS(index), FT_INT}, {"respawntime", ITEMINFO_OFS(respawntime), FT_FLOAT}, {"mins", ITEMINFO_OFS(mins), FT_FLOAT|FT_ARRAY, 3}, {"maxs", ITEMINFO_OFS(maxs), FT_FLOAT|FT_ARRAY, 3}, {NULL, 0, 0} }; //weapon definition static fielddef_t weaponinfo_fields[] = { {"number", WEAPON_OFS(number), FT_INT}, //weapon number {"name", WEAPON_OFS(name),FT_STRING}, //name of the weapon {"level", WEAPON_OFS(level), FT_INT}, {"model", WEAPON_OFS(model), T_STRING}, //model of the weapon {"weaponindex", WEAPON_OFS(weaponindex), FT_INT},//index of weapon in inventory {"flags", WEAPON_OFS(flags), FT_INT},//special flags {"projectile", WEAPON_OFS(projectile), FT_STRING},//projectile used by the weapon {"numprojectiles", WEAPON_OFS(numprojectiles), FT_INT}, //number of projectiles {"hspread", WEAPON_OFS(hspread), FT_FLOAT},//horizontal spread of projectiles (degrees from middle) {"vspread", WEAPON_OFS(vspread), FT_FLOAT},//vertical spread of projectiles (degrees from middle) {"speed", WEAPON_OFS(speed), FT_FLOAT}, //speed of the projectile (0 = instant hit) {"acceleration", WEAPON_OFS(acceleration), FT_FLOAT},//"acceleration" * time (in seconds) + "speed" = projectile speed {"recoil", WEAPON_OFS(recoil), FT_FLOAT|FT_ARRAY, 3},//amount of recoil the player gets from the weapon {"offset", WEAPON_OFS(offset), FT_FLOAT|FT_ARRAY, 3},//projectile start offset relative to eye and view angles {"angleoffset", WEAPON_OFS(angleoffset), FT_FLOAT|FT_ARRAY, 3},//offset of the shoot angles relative to the view angles {"extrazvelocity", WEAPON_OFS(extrazvelocity), FT_FLOAT},//extra z velocity the projectile gets {"ammoamount", WEAPON_OFS(ammoamount), FT_INT}, //ammo amount used per shot {"ammoindex", WEAPON_OFS(ammoindex), FT_INT}, //index of ammo in inventory {"activate", WEAPON_OFS(activate), FT_FLOAT}, //time it takes to select the weapon {"reload", WEAPON_OFS(reload), FT_FLOAT}, //time it takes to reload the weapon {"spinup", WEAPON_OFS(spinup), FT_FLOAT}, //time it takes before first shot {"spindown", WEAPON_OFS(spindown), FT_FLOAT}, //time it takes before weapon stops firing {NULL, 0, 0, 0} }; //projectile definition static fielddef_t projectileinfo_fields[] = { {"name", PROJECTILE_OFS(name), FT_STRING},//name of the projectile {"model", WEAPON_OFS(model), FT_STRING},//model of the projectile {"flags", PROJECTILE_OFS(flags), FT_INT},//special flags {"gravity", PROJECTILE_OFS(gravity), FT_FLOAT}, //amount of gravity applied to the projectile [0,1] {"damage", PROJECTILE_OFS(damage), FT_INT},//damage of the projectile {"radius", PROJECTILE_OFS(radius), FT_FLOAT},//radius of damage {"visdamage", PROJECTILE_OFS(visdamage), FT_INT},//damage of the projectile to visible entities {"damagetype", PROJECTILE_OFS(damagetype), FT_INT},//type of damage (combination of the DAMAGETYPE_? flags) {"healthinc", PROJECTILE_OFS(healthinc), FT_INT},//health increase the owner gets {"push", PROJECTILE_OFS(push), FT_FLOAT},//amount a player is pushed away from the projectile impact {"detonation", PROJECTILE_OFS(detonation), FT_FLOAT},//time before projectile explodes after fire pressed {"bounce", PROJECTILE_OFS(bounce), FT_FLOAT}, //amount the projectile bounces {"bouncefric", PROJECTILE_OFS(bouncefric), FT_FLOAT}, //amount the bounce decreases per bounce {"bouncestop", PROJECTILE_OFS(bouncestop), FT_FLOAT},//minimum bounce value before bouncing stops //recurive projectile definition?? {NULL, 0, 0, 0} };
注意: 我的情况目前有点复杂。然而, 我不知道编译器的名称。环境是Linux的。 这不是我的代码,但我需要编译它。
答案 0 :(得分:3)
宏尝试从包含该成员的struct的开头提取命名成员的偏移量。
而不是WEAPON_OFS(name)
使用offsetof(weaponinfo_t,name)
- 与其他宏类似。
编辑:宏实际上做了什么。
#define WEAPON_OFS(x) (size_t)&(((weaponinfo_t *)0)->x)
这个宏“假装”在地址0处有一个weaponinfo_t
结构,并获取此weaponinfo_t
结构的特定成员的地址。这将产生从结构位置(0)到成员变量位置(0或更高)作为指针的偏移量。然后将指针强制转换为积分,该积分仍然是从结构的开头到成员变量的开始的距离 - 结构中成员变量的偏移量。
显然你的编译器无法解析这个编译时间(完全可以这样做) - 所以你得到一个错误而不是初始化器所需的常量值。
答案 1 :(得分:0)
看起来很有趣的宏从offsetof
重新实现<stddef.h>
。
他们通过要求编译器“假装地址0处有struct foo
的实例,该结构中字段bar
的地址是什么来工作?”
由于0(也称为NULL指针)永远不会被解引用(该字段永远不会被写入或读取,它只是将其地址与&
运算符一起使用),因此这不是未定义的行为。 / p>
由于struct
实例本身的地址为0,因此字段的地址等于该字段从结构起始处的偏移量时,编译器提供的任何地址都是等。