Макрос смещения элемента - нужны подробности - PullRequest
1 голос
/ 28 июня 2010

Пожалуйста, посмотрите на этот макрос.Он используется в Symbian OS SDK, компилятор которого основан на GCC (версия <4). </p>

#ifndef _FOFF
#if __GNUC__ < 4
#define _FOFF(c,f)          (((TInt)&(((c *)0x1000)->f))-0x1000)
#else
#define _FOFF(c,f)          __builtin_offsetof(c,f)
#endif
#endif

Я понимаю, что это вычисление смещения для конкретного члена класса / структуры.Но я не могу понять, как работает это странное утверждение - что такое константа 0x1000 и почему она существует?Может ли кто-нибудь объяснить мне это?

Ответы [ 3 ]

2 голосов
/ 28 июня 2010

Imo 0x1000 это просто случайно выбранное число. Это неверный указатель, и вы, вероятно, могли бы использовать ноль вместо него.

Как это работает:

  1. Преобразует 0x1000 в указатель класса (указатель типа c). - (с *) 0x1000
  2. Принимает указатель на член "f" класса c - & (((c *) 0x1000) -> f)
  3. Бросает в TInt. ((TInt) & (((c *) 0x1000) -> f))
  4. Вычитает целочисленное значение указателя на базу (в данном случае 0x1000) из целочисленного значения указателя на член c: (((TInt) & (((c *) 0x1000) -> f)) - 0x1000)

Поскольку f не записывается, нет прав доступа / segfault.

Возможно, вы могли бы использовать ноль вместо 0x1000 и отказаться от вычитания (т.е. просто использовать "((TInt) & (((c *) 0x0000) -> f))"), но, возможно, автор подумал, что вычитая базовый указатель из указатель на член является более "правильным" способом, чем попытка напрямую привести указатель к целому числу. Или, может быть, компилятор предоставляет «скрытые» члены класса, которые могут иметь отрицательное смещение (что возможно в некоторых компиляторах - например, Delphi Compiler (я знаю, что это не c ++) предоставил несколько скрытых «полей», которые были расположены перед «self» (аналог «this»), в этом случае имеет смысл использовать 0x1000 вместо 0.

1 голос
/ 28 июня 2010

"Если бы был элемент struct c, начинающийся точно с (идеально выровненного ;-) адреса 0x1000, то по какому адресу был бы член структуры f?"- ответ: смещение, которое вы ищете, за исключением, конечно, гипотетического начального адреса 0x1000 для структуры ... с разницей, расстоянием или смещением АКА, вычисляемым как целые числа, в противном случае автоматическое масштабирование в адресной арифметике выбрасывает васoff (откуда приведен).

Какие части выражения, в частности, доставляют вам проблемы?

Внутренняя часть &(((c *)0x1000)->f) является «адресом члена f гипотетическогоstruct c, расположенная в 0x1000. Прямо перед ней находится приведение (я предполагаю, что TInt, конечно, является целочисленным типом), затем - 0x1000, чтобы получить смещение (расстояние АКА или разницу междуадрес конкретного заинтересованного члена и начало всей структуры).

1 голос
/ 28 июня 2010

Он обрабатывает относительный адрес 'f' как члена класса / структуры по адресу 0x1000, а затем вычитает 0x1000, так что возвращается только разница между адресом класса / структуры и адресом функции-члена.Я предполагаю, что ненулевое значение (то есть 0x1000) используется, чтобы избежать обнаружения нулевого указателя.

...