Мне нужно переписать эту строку кода и нужна помощь - PullRequest
1 голос
/ 13 апреля 2011

Я пытаюсь скомпилировать этот фрагмент кода, найденный ниже. Однако я получил сообщение об ошибке «Значение инициализации должно быть константным выражением.» В каждой строке определений iteminfo_fields, armsinfo_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 tho. Это не мой код, но мне нужно его скомпилировать.

Ответы [ 2 ]

3 голосов
/ 13 апреля 2011

Макросы пытаются извлечь смещение именованного элемента из начала структуры, содержащей этот элемент.

Вместо WEAPON_OFS(name) используйте offsetof(weaponinfo_t,name) - и аналогично для других макросов.

РЕДАКТИРОВАТЬ: Что на самом деле делают макросы.

#define WEAPON_OFS(x) (size_t)&(((weaponinfo_t *)0)->x)

Этот макрос "притворяется", что существует структура weaponinfo_t по адресу 0, и принимает адрес определенного члена этой структуры weaponinfo_t. Это дает смещение от расположения структур (0) до расположения переменных-членов (0 или выше) в качестве указателя. Затем указатель приводится к интегралу, который по-прежнему представляет собой расстояние от начала структуры до начала переменной-члена - смещение переменной-члена в структуре.

Очевидно, ваш компилятор не может разрешить это время компиляции (что вполне возможно сделать, хотя), поэтому вы получаете ошибку вместо постоянного значения, необходимого для ваших инициализаторов.

0 голосов
/ 13 апреля 2011

Интересные макросы повторно реализуют <a href="http://linux.die.net/man/3/offsetof" rel="nofollow">offsetof</a>, из <stddef.h>.

Они работают, спрашивая компилятор "притвориться, что есть экземпляр struct foo по адресу 0, что является адресомполя bar в этой структуре? "

Поскольку 0 (также известный как указатель NULL) никогда не разыменовывается (поле никогда не записывается и не читается, его адрес просто берется с помощью & оператор), это не неопределенное поведение.

Поскольку адрес самого экземпляра struct равен 0, независимо от того, какой адрес компилятор придет, так как адрес поля будет равен смещению этого поля отначало структуры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...