Статья "От зелёного к красному", указатель на структуру.

Тема в разделе "WASM.BEGINNERS", создана пользователем amvoz, 24 окт 2009.

  1. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    653
    Друзья!
    Вот здесь на нашем сайте такая статья
    http://www.wasm.ru/article.php?article=green2red02

    И вот там среди прочего работа с таблицей экспорта. И вот я что-то встрял.
    Вот есть такая структура у меня в файле winnt.h

    Код (Text):
    1. typedef struct _IMAGE_EXPORT_DIRECTORY {
    2.     DWORD Characteristics;
    3.     DWORD TimeDateStamp;
    4.     WORD MajorVersion;
    5.     WORD MinorVersion;
    6.     DWORD Name;
    7.     DWORD Base;
    8.     DWORD NumberOfFunctions;
    9.     DWORD NumberOfNames;
    10.     DWORD AddressOfFunctions;
    11.     DWORD AddressOfNames;
    12.     DWORD AddressOfNameOrdinals;
    13. } IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;
    Описание полей все даны в статье, понятно всё, поковырялся, разобрался. А дальше идёт код и там такое вот объявление

    Код (Text):
    1. PIMAGE_EXPORT_DIRECTORY Export=(PIMAGE_EXPORT_DIRECTORY)
    2. RVAtoOffset((long)hMap,ExportRVA);
    ...Код, скомпилился, но вылетело исключение какое-то, но дело не в нём. Начал я разбираться и понял, что в моём понимании есть пробел, а именно:

    PIMAGE_EXPORT_DIRECTORY Export
    Как это компилится? Не пойму.
    Смотрите, PIMAGE_EXPORT_DIRECTORY это не имя типа. Если бы это было имя типа- было бы понятно- объявляем переменную Export типа PIMAGE_EXPORT_DIRECTORY и сразу же её иницилизируем.

    Но нет! PIMAGE_EXPORT_DIRECTORY это всего лишь указатель!

    То есть такой синтаксис рабочий:
    <имя указателя> <имя переменной>
    Разъясните, пожалуйста, как такой синтаксис может быть рабочим! Тем более, что в других ситуациях это не срабатывает.

    ...Чтобы не быть голословным- вот ситуация один к одному.
    Код (Text):
    1. int main () {
    2.  struct struktura {
    3.   int r;
    4.  } a,*pa;
    5.  pa b;
    6. }
    Вот ПРЕДСКАЗУЕМО не компилится.
    Ибо "pa b" это ерунда какая-то.
    Но только не в первом примере!
    Помогите, пожалуйста, разобраться! Спасибо.
     
  2. JCronuz

    JCronuz New Member

    Публикаций:
    0
    Регистрация:
    26 сен 2007
    Сообщения:
    1.240
    Адрес:
    Russia
    Код (Text):
    1. typedef struct struktura {
    2.   int r;
    3. } a,*pa;
     
  3. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    amvoz
    Тип переменной/указателя здесь — это всё, начиная со слова struct и заканчивая закрывающей фигурной скобкой. typedef позволяет создать "синоним" для такого типа, чтобы не писать каждый раз описание стурктуры.
    Т.о. кусок кода из winnt.h объявляет синоним, после чего этот синоним можно использовать в объявлении переменных. Ваш же код объявляет сразу переменную a типа описываемой структуры и указатель pa того же типа. Соответственно использовать их, как типы нельзя.
     
  4. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    653
    Да, я забыл написать typedef.
    Непонятности начинаются, когда после неё идёт указатель какой-нибудь.
    Смотрите первый пример.

    То есть мне понятно, что таким образом объявляется, допустим IMAGE_EXPORT_DIRECTORY как синоним типа _IMAGE_EXPORT_DIRECTORY

    После этого можно писать:
    IMAGE_EXPORT_DIRECTORY per;

    Что равнозначно
    _IMAGE_EXPORT_DIRECTORY per;

    И такое обращение будет правильно:
    per.NumberOfFunctions= cafebabe;

    Это всё понятно.
    Но в первом примере указатель-то что значит?

    *PIMAGE_EXPORT_DIRECTORY получается синоним имени типа _IMAGE_EXPORT_DIRECTORY?
    Но это не так ведь...
     
  5. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    amvoz
    В первом примере создаётся синоним типа "указатель на структуру". Т.е. после него объявление
    Код (Text):
    1. struct {
    2.     DWORD Characteristics;
    3.     DWORD TimeDateStamp;
    4.     WORD MajorVersion;
    5.     WORD MinorVersion;
    6.     DWORD Name;
    7.     DWORD Base;
    8.     DWORD NumberOfFunctions;
    9.     DWORD NumberOfNames;
    10.     DWORD AddressOfFunctions;
    11.     DWORD AddressOfNames;
    12.     DWORD AddressOfNameOrdinals;
    13. } * myStructPtr;
    , объявление
    Код (Text):
    1. _IMAGE_EXPORT_DIRECTORY * myStructPtr;
    и объявление
    Код (Text):
    1. PIMAGE_EXPORT_DIRECTORY myStructPtr;
    будут иметь идентичный смысл.
     
  6. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    653
    Вон оно как... То есть был тип: указатель на структуру типа _IMAGE_EXPORT_DIRECTORY:
    _IMAGE_EXPORT_DIRECTORY*;

    Потом мы ввели синоним вышеупомянутого типа PIMAGE_EXPORT_DIRECTORY:
    typedef _IMAGE_EXPORT_DIRECTORY* PIMAGE_EXPORT_DIRECTORY;

    Теперь имеем тип PIMAGE_EXPORT_DIRECTORY (вернее, синоним типа _IMAGE_EXPORT_DIRECTORY*) и можем объявлять переменные такого типа
    PIMAGE_EXPORT_DIRECTORY per;

    Так, да? Вроде теперь всё стало на свои места. Спасибо.
     
  7. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    amvoz
    Почти... Структура типа
    Код (Text):
    1. struct {
    2.     DWORD Characteristics;
    3.     DWORD TimeDateStamp;
    4.     WORD MajorVersion;
    5.     WORD MinorVersion;
    6.     DWORD Name;
    7.     DWORD Base;
    8.     DWORD NumberOfFunctions;
    9.     DWORD NumberOfNames;
    10.     DWORD AddressOfFunctions;
    11.     DWORD AddressOfNames;
    12.     DWORD AddressOfNameOrdinals;
    13. }
    А засовывать _IMAGE_EXPORT_DIRECTORY после слова struct — это, если не ошибаюсь, новомодный способ задавать синонимы структурам, и раньше это можно было делать только через typedef. Хотя не уверен. Я — не спец. :)
    В остальном всё верно.