Определяет ли стандарт c , как передавать этот указатель функциям-членам?

#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 define virtual void func() , и производный класс ABC : public A, public B, public C переопределяются func() , MSVC сгенерирует два блока: один для настройки ABC адреса this указателя при ABC::B::func() вызове, а другой для его настройки при ABC::C::func() вызове. (В моих тестах A он не будет получен, потому A что начинается с байта 0 ABC , и, следовательно, любой экземпляр ABC* this и его A* this точка указывают на один и тот же адрес.)

4. Конечно, эта проблема возникает только в том случае, если вы наследуете от нескольких базовых классов, два или более из которых определяют виртуальную функцию с одинаковой сигнатурой, и эта же функция затем переопределяется производным классом. Но, тем не менее, это один из методов, используемых компиляторами при обработке this и виртуальных функций.