#c
#c
Вопрос:
Почти все знают, что член класса получает указатель this в качестве первого «невидимого» параметра функции. Это указано в стандарте C ? Может ли определенная реализация компилятора передать его другим способом? Например, выделенный реестр.
Комментарии:
1. Стандарт ничего не знает о регистрах — это не относящиеся к делу детали реализации. Стандарт определяет только, какие наблюдаемые побочные эффекты должна производить соответствующая программа. Реализация может делать все, что ей заблагорассудится, для достижения этих побочных эффектов. Смотрите также: en.cppreference.com/w/cpp/language/as_if
2. Как передаются аргументы (включая подразумеваемый
this
аргумент), это вопрос для данной платформы ABI, а не для языкового стандарта. В современных ABI большинство аргументов передаются в регистрах процессора.3. Соглашение о вызовах, безусловно, диктует это. И это может быть явно указано, поэтому компилятор, я бы подумал, что по умолчанию
cdecl
используется или используется указанный?4. @lfgtm «Соглашение о вызовах… может быть явно указано» Стандарт C не предоставляет никакого способа сделать это и никогда не упоминает термин «соглашение о вызовах». Любой такой механизм обязательно зависит от реализации.
5. «Может ли определенная реализация компилятора передать его другим способом? Например, выделенный реестр. »
__thiscall
Соглашение о вызовах MSVC делает именно это —this
передается в регистре ECX, остальные аргументы отправляются в стек.
Ответ №1:
Конечно, именно так были реализованы самые первые версии C (ранний C был преобразован в код C), но будьте уверены, что стандарт C этого не требует.
Передача его в качестве последнего значения параметра также представляется возможной, а для виртуальных функций — совсем другой метод.
Комментарии:
1. Кто-нибудь знает компилятор, который не передается
this
в качестве первого параметра?2. @AndyG MSVC.
__thiscall
соглашение о вызовах передаетсяthis
в регистре ECX, в то время как аргументы передаются в стек.3.
virtual
функции, по крайней мере, в некоторых компиляторах (таких как MSVC), иногда используют модуль настройки, чтобы помочь с вызовом определенных версий. Если классыA
,B
, иC
definevirtual void func()
, и производный классABC : public A, public B, public C
переопределяютсяfunc()
, MSVC сгенерирует два блока: один для настройкиABC
адресаthis
указателя приABC::B::func()
вызове, а другой для его настройки приABC::C::func()
вызове. (В моих тестахA
он не будет получен, потомуA
что начинается с байта 0ABC
, и, следовательно, любой экземплярABC* this
и егоA* this
точка указывают на один и тот же адрес.)4. Конечно, эта проблема возникает только в том случае, если вы наследуете от нескольких базовых классов, два или более из которых определяют виртуальную функцию с одинаковой сигнатурой, и эта же функция затем переопределяется производным классом. Но, тем не менее, это один из методов, используемых компиляторами при обработке
this
и виртуальных функций.