Тема: Адресація параметрів функції
Доброго дня, панове. Одразу хочу повідомити, що працюю на 64-розрядній системі Windows, надалі це, напевно, знадобиться. Розбирався сьогодні з черговою лабораторною, темою якої є функції з неоголошеними параметрами. У ній мені довелося розробити три версії функції, яка повертала б номер точки найвіддаленішої від початку координат. Точка задається структурою, полями якої є 3 змінні типу double. У першій версії функції спочатку вказується кількість параметрів, а далі самі параметри-структури; у другій версії мені потрібно було перед кожною точкою вказувати її номер. Для зручності я використав бібліотеку stdarg.h. З цими версіями труднощі не виникли, цікавіше стало з третьою версією. Параметри такі ж, але я вирішив використати нетипізований вказівник, щоб опрацьовувати параметри. Перше, що я помітив це те, що моя структура розширяється компілятором для вирівнювання з 24 до 64 байтів. Наступним я помітив, що якщо, наприклад, порядок параметрів: int, Point(користувацький тип структури), int, то адреса параметра-структури буде більшою, ніж другого цілочислового значення. Це мені видалося трохи дивним і одночасно цікавим, адже, наскільки я знаю, параметри розташовуються в стеці по-порядку. Отож я взяв цей тип структури, розробив кілька тестових функцій з різними параметрами й виводив адреси параметрів. Результати були такі ж. Хотів взнати з чим зв'язано таке розташування об'єктів в пам'яті. Нижче прикріплю код тестової програми і скріншоти з результатами.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdarg.h>
#define SQR(x) ((x)*(x))
typedef struct {
double x, y, z;
} Point;
void TestParams1(int, double, Point, int, double, Point);
void TestParams2(Point, Point, double, int, int, double);
void TestParams3(int, int, Point, Point, double, double);
void TestParams4(double, int, Point, int, int*, Point*, Point, double, double*);
int main(void) {
system("chcp 1251");
Point a = { 2.5, 6.3, 10.0 }, b = { 7.2, 14.1, 3.05 }, c = { 2.0, 3.8, 4.7 }, d = { 10.6, 3.4, 5.0 }, e = { 3.2, 10.9, 7.6 };
int int_num = 432;
double dob_num = 23.12;
/*Тест 1*/
printf("Тест 1:\n");
TestParams1(1, 4.0, a, 10, 6.54, b);
/*Тест 2*/
printf("Тест 2:\n");
TestParams2(c, d, 10.23, 4, 3, 87.32);
/*Тест 3*/
printf("Тест 3:\n");
TestParams3(1, 4, a, e, 6.1, 3.21);
/*Тест 4*/
printf("Тест 4:\n");
TestParams4(23.6, 4, c, 11, &int_num, &d, a, 65.87, &dob_num);
}
void TestParams1(int arg_int1, double arg_dob1, Point arg_Point1, int arg_int2, double arg_dob2, Point arg_Point2)
{
printf(" &arg_int1=%p, &arg_dob1=%p, &arg_Point1=%p \n", &arg_int1, &arg_dob1, &arg_Point1);
printf(" &arg_int2=%p, &arg_dob2=%p, &arg_Point2=%p \n", &arg_int2, &arg_dob2, &arg_Point2);
}
void TestParams2(Point arg_Point1, Point arg_Point2, double arg_dob1, int arg_int1, int arg_int2, double arg_dob2)
{
printf(" &arg_Point1=%p, &arg_Point2=%p, &arg_dob1=%p \n", &arg_Point1, &arg_Point2, &arg_dob1);
printf(" &arg_int1=%p, &arg_int2=%p, &arg_dob2=%p, \n", &arg_int1, &arg_int2, &arg_dob2);
}
void TestParams3(int arg_int1, int arg_int2, Point arg_Point1, Point arg_Point2, double arg_dob1, double arg_dob2)
{
printf(" &arg_int1=%p, &arg_int2=%p, &arg_Point1=%p \n", &arg_int1, &arg_int2, &arg_Point1);
printf(" &arg_Point2=%p, &arg_dob1=%p, &arg_dob2=%p, \n", &arg_Point2, &arg_dob1, &arg_dob2);
}
void TestParams4(double arg_dob1, int arg_int1, Point arg_Point1, int arg_int2, int* p_int1, Point* p_Point1, Point arg_Point2, double arg_dob2, double* p_dob1)
{
printf(" &arg_dob1=%p, &arg_int1=%p, &arg_Point1=%p \n", &arg_dob1, &arg_int1, &arg_Point1);
printf(" &arg_int2=%p, &p_int1=%p, &p_Point1=%p \n", &arg_int2, &p_int1, &p_Point1);
printf(" &arg_Point2=%p, &arg_dob2=%p, &p_dob1=%p, \n", &arg_Point2, &arg_dob2, &p_dob1);
}
Тестові функції:
Результати: