_ _cdecl, _fastcall, _stdcall - соглашение о вызове функции
Соглашения включают понятия:
Способ передачи параметров (порядок размещения параметров в стеке);
2. кто восстанавливает стек – вызывающая или вызываемая функция;
3. способ хранения имён функций в объектном модуле;
Пример: пусть существует функция вида:
void calltype f(char c, short s, int i); main() { f(‘A’, 10,9999 , 1.23)
Адрес возврата A 10 9999 1,23
//вызов
возврат организован командой ret()
сdecl - параметры формируются справа налево.
_stdcall (в стиле Паскаль) – используется для уменьшения объёма исполняемого файла.
_f@20
//количество байт, занимаемое параметром в стеке
Способы передачи параметров
по значению по адресу
по указателю по ссылке(C++)
Передача параметров по значению – простая передача в стеке, не оставляющая возможности для изменения самих переменных, вызывающих функцию.
Передача параметров по адресу – способ предполагает, что функция получает не копии объектов, а их адреса. При этом программист получает возможность изменить значение объекта по этому адресу. Вызовы подразделяются на вызовы по ссылке и по адресу.
Если при передаче адреса требуется запретить функции модифицировать значения по этому адресу, используется ключевое слово const.
main() { int a=2, b=1, r1, r2; fp(a,b,&r1,&r2); }
указатель: void fp(int x, int y, int *sub,int sum) { sum=x+y; sub=x-y; }
main() { int a=2, b=1,r1,r2; fr(a,b,r1,r2); }
ссылка: void fr ( int x, int y, int sum, int sub) { sum=x+y; sub=x-y; }
int My (const char *p) { int n=0; while (*p) { p++; n++; } return n; }
main() { char ar[10]=”QWERTY” int count = My(ar) count=My(“ABC”);
}
void f(int*) main() { int x=1; int 8p=&x; f(p); f(&x); }
int f1(); void f2(int, int) main() { int x=1; y=5; int z=f1(); int w=x+y; f2(z,w); // f2(f1(), x+y);
}
Использование “ , ” , формирование параметров.
void f(int); int main() { int x; std: cin>>x; f(x); // f (cin>>x, x); }
Указатели на массивы в качестве параметров функции.
Компилятор Си никогда не передаёт массивов по значению. Передаётся только указатель на массив. int ar1[k]; int ar2[k][m]; F(ar1,ar2); void F(int *p1, int (*p2)[M]) int **p2; void F(int p1[], int p2[][M])
Значения аргументов функций по умолчанию.
void f (char, int, float); f(‘A’, 3, 2.4); void f1 (char, int, double=1.5); f1(‘A’, 3, 2.4); // по умолчанию можно использовать >=1 аргумента, но все они должны располагаться в конце списка аргументов f1(‘A’, 3);
Замечание: поставить запятую вместо пропущенного параметра по умолчанию НЕЛЬЗЯ!! f1(‘A’, , 3.2);
c=10;
a=f;
Блок схемы.
Имя функции, передаваемые параметры
нет да
Имя функции
Переменное число параметров функции.
Си допускает использование переменного числа параметров.
Специфика вызова:
Признаком функции с переменным числом аргументов является многоточие в списке параметров;
2) встретив … компилятор прекращает контроль соответствующего типа;
У функции должен быть хотя бы один обязательный параметр;
Функция с переменным числом параметров должна иметь способ определения их точного числа при каждом вызове;
int Func(int i; …); int Func (int i, float z, …);
Признаком конца списка параметров является -1.
int Func(int i, …) { int count=0, sum=0; int *p=&i; while(*p!=-1) { count ++; sum+=*p++; } return sum; }
Функции стандартной библиотеки
(printf, scanf).
int printf( const char *, …);
Функция printf предназначена для перевода указанных программистом в качестве необязательных параметров значений в строковое представление.
Функция определяет точное число необязательных параметров, подсчитывая количество символов % в единственном обязательном параметре.
%c – char
%d – int
%i – int
%e – exp // x=1,1e+0,02
%f – float
%g – float , но без лишних нулей
%o – восьмеричное представление числа
%p – значение адреса указателя в шестнадцатеричном виде
%s – массив строк
%u – преобразование аргумента к целому беззнаковому в десятичном виде
%x - преобразование аргумента к целому беззнаковому в шестнадцатеричном виде
int m = -1;
printf(“%x”,m);
%[+-n]s (строка символов)
%[+-n]f (дробное число в фиксированном формате)
%[+-n]e (количество цифр после десятичной точки)
%[+-n]i (d) (количество выводимых цифр)
%[+-n]g (максимальное количество цифр)
Виды возвращаемых значений и механизмы их формирования.
Пользовательский тип
Адрес
Базовый тип
Возвращаемое значение
указатель
ссылка
Функция может возвращать:
-объект базового типа;
-объект пользовательского типа;
-указатель или ссылку;
bool func(); //базовый тип main() { bool b= Func(); }
int &f() { static int n; return n; }
Проблемы при возвращении ссылки или указателя.
int *f1(int n) { int nN=n*5; //return &nN; } //функция возвращает указатель на область памяти в стеке, которая после возвращения из функции может быть задействована компилятором для других целей
int &f2(int n) { int nN=n*5; return nN; } //функция возвращает указатель на локальную временную переменную
int main() { z=f2(1) +f2(2)+f2(3); }
Нельзя возвращать адреса локальных объектов.
Возвращать можно:
Указатель или ссылку на объект со статическим временем существования;