Это все зависит от вас, если вызывающий абонент ваш код.Если вызывающий не находится под вашим контролем, вы должны либо следовать его существующему соглашению, либо совместно разрабатывать свое собственное соглашение.
Например, на платформе x86, когда арифметика с плавающей запятой обрабатывается инструкциями FPU, результатфункция возвращается как верхнее значение в стеке регистров FPU.(Если вы знаете, регистры x86 FPU организованы в своего рода «круговой стек»).В этот момент это не float
и double
, это значение, хранящееся с внутренней точностью FPU (которое может быть выше float
или double
), и вызывающая сторона несет ответственность за получение этого значения сверхустека FPU и преобразовать его в любой тип, который он пожелает.Фактически, именно так работает типичная инструкция FPU: она берет свои аргументы с вершины стека FPU и переносит результат обратно в стек FPU.Реализуя свою функцию таким же образом, вы по существу эмулируете «сложную» инструкцию FPU с вашей функцией - довольно естественный способ сделать это.
Когда арифметика с плавающей точкой обрабатывается инструкциями SSE, вы можете выбрать несколькоSSE регистрируется для той же цели (используйте xmm0
точно так же, как вы используете EAX
для целых чисел).
Для сложных структур (то есть тех, которые больше, чем регистр или пара регистров), вызывающая сторонаобычно передают указатель на зарезервированный буфер функции.И функция поместит результат в буфер.Другими словами, на самом деле функции никогда не «возвращают» большие объекты, а создают их в буфере памяти, предоставленном вызывающей стороной.
Конечно, вы можете использовать этот метод «буфера памяти» для возврата значений.любого типа, но с меньшими значениями, то есть значениями скалярного типа, гораздо эффективнее использовать регистры, чем ячейку памяти.Кстати, это относится и к небольшим структурам.
Перечисления обычно являются просто концептуальной оболочкой для некоторого целочисленного типа.Таким образом, нет разницы между возвращением перечисления или целого числа.