Реально ли заталкивать в стек всю структуру, а не указатель на нее?

Тема в разделе "LANGS.C", создана пользователем Magnum, 13 дек 2011.

  1. Magnum

    Magnum New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2007
    Сообщения:
    925
    Есть структура:

    Код (Text):
    1. typedef struct
    2. {
    3.  CHAR szName[20];
    4.  DWORD dwIndex;
    5.  // .... etc
    6. } REGULAR_CONTAINER_DATA;
    Общий размер структуры 80 байт.
    Понадобилось оформить функцию, которой аргументом нужно передать данную структуру.
    Передать именно через стек, а не указателем.
    Да, можно выделить память и передать указатель на нее функции, либо много других разных вариантов.
    Но меня интересует именно этот. Реально ли научить компилятор передавать всю структуру целиком в стек (т.е. не push [pContainerData], а что-то вроде push [part_1], push [part_2], push ... и так всю структуру)?
     
  2. Sholar

    Sholar New Member

    Публикаций:
    0
    Регистрация:
    16 окт 2011
    Сообщения:
    189
    Обычно компилятор копирует структуру и передает в функцию указатель на скопированную структуру(чтобы не затереть оригинал). При таком подходе результат будет точно таким же, как если бы структура передавалась в стек по частям командами push. Вы объясните зачем это вообще нужно, может тогда легче будет вам помочь.
     
  3. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Magnum
    Структуры в функции и так по значению передаются, а не по указателю.
     
  4. iZzz32

    iZzz32 Sergey Sfeli

    Публикаций:
    0
    Регистрация:
    3 сен 2006
    Сообщения:
    355
    В stdcall, cdecl и ms-fastcall передаётся не указатель на копию, а именно сама структура (цепочка push, если структура небольшая, в противном случае какой-нибудь movsd). То, о чём вы говорите – оптимизация, когда конвенцию вызовов можно безболезненно нарушить (например, функция статическая и на неё нигде не берётся указатель).
     
  5. FatMoon

    FatMoon New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2002
    Сообщения:
    954
    Адрес:
    Russia
    сомнительно. Может быть вы путаете цепочку пушей при создании КАДРА? потому что локальные переменные одной процедуры могут передаваться в кадрах вложенным процедурам. Особенно с учетом, что ENTER/LEAVE не самые оптимальные по скорости. Иначе передавать структуру через стек как-то кривовато, хоть какое соглашение используй. А как байтовые члены структур передаются? или 2-байтовые? А если размер структуры не кратен 4?
     
  6. iZzz32

    iZzz32 Sergey Sfeli

    Публикаций:
    0
    Регистрация:
    3 сен 2006
    Сообщения:
    355
    Я давно уже не ковырялся в соглашениях, но вроде ничего не путаю. Как минимум можно посмотреть, что будет в retn у кода ниже, а будет там не размер указателя явно:
    Код (Text):
    1. struct t { int data[256]; }; void __stdcall foo(struct t arg) { return; }
    И я не понимаю, причём тут члены – вот если размер структуры не кратнен 4 будет, её, видимо, выравняют на 4 (а как иначе-то?) перед передачей. Это я всё про 32 бита, если что.

    Вот при возврате структур – там да, указатели. Если размер структуры не равен 1/2/4/8 байтам (иначе она преспокойно возвращается в AL/AX/EAX/EDX:EAX), вызывающая функция создаёт буфер, передаёт первым аргументом указатель на него, а вызываемая функция копирует результат туда и дополнительно возвращает тот же самый указатель в EAX.
     
  7. Sholar

    Sholar New Member

    Публикаций:
    0
    Регистрация:
    16 окт 2011
    Сообщения:
    189
  8. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Sholar
    Код и дизасм в студию. У меня вызов foo в следующей функции (пришлось подкорректировать во избежание оптимизаций):
    Код (Text):
    1. struct t { int data[256]; };
    2. void __stdcall foo(struct t arg, int num)
    3. {
    4.     printf("%u", arg.data[num]);
    5.     if (num < 50)
    6.     {
    7.         arg.data[num] = num;
    8.         foo(arg, num+1);
    9.     }
    10.     return;
    11. }
    выглядит так:
    Код (Text):
    1. Address   Hex dump          Command
    2. 00FC104C  |.  46            INC ESI
    3. 00FC104D  |.  56            PUSH ESI
    4. 00FC104E  |.  81EC 00040000 SUB ESP,400
    5. 00FC1054  |.  8BFC          MOV EDI,ESP
    6. 00FC1056  |.  B9 00010000   MOV ECX,100
    7. 00FC105B  |.  8DB5 FCFBFFFF LEA ESI,[EBP-404]
    8. 00FC1061  |.  F3:A5         REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
    9. 00FC1063  |.  E8 98FFFFFF   CALL foo
    Т.е. никаких указателей. Вся структура прямо в стек уходит.

    P.S. Ага. Уже сами разобрались. Ну и ладно. :)
     
  9. Magnum

    Magnum New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2007
    Сообщения:
    925
    Всем большое спасибо! Тема закрыта! Оказывается велосипед изобрели задолго до меня :)