2014-11-06 2 views
0

Как компилятор C проходит и возвращает struct/union в/из функции? Является ли структура нажатой в стек перед вызовом функции, это только ссылка структуры, которая передается функции?Передача структуры/объединения функции в C

Тот же вопрос касается возврата. Что точно возвращает функция?

typedef struct { 
    long m4; 
    long m3; 
    long m2; 
    long m1; 
} ext_components_t; 

typedef union { 
    long array[sizeof(int_components_t)]; 
    int_components_t comp; 
} int_components_u; 

typedef union { 
    long array[sizeof(ext_components_t)]; 
    ext_components_t comp; 
} ext_components_u; 

#pragma never_inline 
ext_components_u transfer(int_components_u m) 
{ 
    ext_components_u out; 
    out.comp.m1 = 10*m.comp.a+11*m.comp.b+12*m.comp.c; 
    out.comp.m2 = 20*m.comp.a+21*m.comp.b+22*m.comp.c; 
    out.comp.m3 = 30*m.comp.a+31*m.comp.b+32*m.comp.c; 
    out.comp.m4 = 40*m.comp.a+41*m.comp.b+42*m.comp.c; 
    return out; 
} 

volatile int_components_u x; 
volatile ext_components_u y; 
void main() 
{ 
    y = transfer(x); 
} 

Вот мое предположение (псевдо-код):

push_stack(x.array[0]) 
push_stack(x.array[1]) 
push_stack(x.array[2]) 

call transfer 

y.array[0] = shift_stack() 
y.array[1] = shift_stack() 
y.array[2] = shift_stack() 
y.array[3] = shift_stack() 

Или другое решение может быть:

call transfer(&x) 
y.array[0] = shift_stack() 
y.array[1] = shift_stack() 
y.array[2] = shift_stack() 
y.array[3] = shift_stack() 
+0

Это зависит от реализации. Обычно реализация будет следовать за платформой ABI. –

ответ

6

В C все аргументы функции передаются по значению. Это означает, что структуры и объединения скопированы при передаче функций. То, как выполняется это копирование, зависит от реализации, но наиболее распространенным способом является выделение пространства в стеке и копирование содержимого структуры/объединения в это пространство.

То же самое касается возвращаемых данных, оно возвращается значением (то есть скопировано).


Здесь важно отметить, что C не имеет доступа к ссылке. Когда вы передаете указатель, это указатель , который передается по значению, т. Е. Копируется.

Однако, вы можете использовать указатели для emulate, проходящие по ссылке.

+3

Это не повсеместно. В стандарте нет ничего, что бы требовало, чтобы структуры и союзы были переданы в стек. ABI может позволить им проходить через регистры. –

+0

@DavidHeffernan Вы правы, обновленный ответ. –

+1

@DavidHeffernan Я почти уверен, что в стандарте нет ничего, что гарантирует, что даже существует стек. :) – unwind

2

Как передать структуры и вернуть структуры, зависит от реализации. Обычно они копируются в стек. Параметры передаются в регистры (для скорости), где это возможно.

Реализация может передать int и структуру, содержащую только int member по-разному. Аналогичные правила применяются и к профсоюзам.

Некоторые книги говорят, что «параметры передаются вызываемой функции, нажимая их на стек справа налево». Это упрощение. (От программирования эксперта C Deep C секреты Питера Ван дер Линдена)

Смежные вопросы