#define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include using namespace std; void print_in_hex(const void* data, size_t size) { const uint8_t* bytes = static_cast(data); for (size_t i = 0; i < size; ++i) { cout << hex << uppercase << static_cast(bytes[i] / 16) << static_cast(bytes[i] % 16); cout << ' '; if ((i + 1) % 16 == 0 || i == size - 1) cout << endl; } cout << dec; } void print_in_hex(uint8_t byte) { cout << hex << uppercase << static_cast(byte / 16) << static_cast(byte % 16) << dec; } struct Student { char name[17]; // 17 байт uint16_t admission_year; // 2 байта float average_score; // 4 байта unsigned int gender : 1; // 1 бит unsigned int courses : 7; // 7 бит (вместе с gender = 1 байт) Student* monitor; // 8 байт (в 64-битной системе) }; void print_student_info() { Student students[3]; strcpy(students[0].name, "Иванов Иван"); students[0].admission_year = 2022; students[0].average_score = 4.5f; students[0].gender = 1; students[0].courses = 12; students[0].monitor = nullptr; // староста strcpy(students[1].name, "Петрова Анна"); students[1].admission_year = 2022; students[1].average_score = 4.8f; students[1].gender = 0; students[1].courses = 10; students[1].monitor = &students[0]; strcpy(students[2].name, "Сидоров Петр"); students[2].admission_year = 2022; students[2].average_score = 4.2f; students[2].gender = 1; students[2].courses = 11; students[2].monitor = &students[0]; cout << "1. Адрес и размер массива:" << endl; cout << "Адрес массива: " << &students << endl; cout << "Размер массива: " << sizeof(students) << " байт" << endl; cout << "\n2. Адреса и размеры элементов массива:" << endl; for (int i = 0; i < 3; ++i) { cout << "\nСтудент " << i << ":" << endl; cout << "Адрес: " << &students[i] << endl; cout << "Размер: " << sizeof(students[i]) << " байт" << endl; } Student* s = &students[1]; cout << "\n3. Детальная информация о полях второго студента:" << endl; cout << "\nПоле name:" << endl; cout << "Адрес: " << static_cast(&s->name) << endl; cout << "Смещение: " << offsetof(Student, name) << " байт" << endl; cout << "Размер: " << sizeof(s->name) << " байт" << endl; cout << "Значение: \"" << s->name << "\"" << endl; cout << "\nПоле admission_year:" << endl; cout << "Адрес: " << &s->admission_year << endl; cout << "Смещение: " << offsetof(Student, admission_year) << " байт" << endl; cout << "Размер: " << sizeof(s->admission_year) << " байт" << endl; cout << "Значение: " << s->admission_year << endl; cout << "Шестнадцатеричное значение: "; print_in_hex(reinterpret_cast(&s->admission_year), sizeof(s->admission_year)); cout << endl; cout << "Двоичное значение: " << bitset<16>(s->admission_year) << endl; cout << "\nПоле average_score:" << endl; cout << "Адрес: " << &s->average_score << endl; cout << "Смещение: " << offsetof(Student, average_score) << " байт" << endl; cout << "Размер: " << sizeof(s->average_score) << " байт" << endl; cout << "Значение: " << s->average_score << endl; uint32_t float_as_int; memcpy(&float_as_int, &s->average_score, sizeof(float)); cout << "Шестнадцатеричное значение: "; print_in_hex(reinterpret_cast(&s->average_score), sizeof(s->average_score)); cout << endl; cout << "Двоичное значение: " << bitset<32>(float_as_int) << endl; cout << "\nПоле gender и courses (битовые поля):" << endl; // Получаем значения битовых полей unsigned int gender_value = s->gender; unsigned int courses_value = s->courses; // Вычисляем адрес области битовых полей экспериментально // Битовые поля идут после average_score uint8_t* start_of_struct = reinterpret_cast(s); uint8_t* after_avg_score = reinterpret_cast(&s->average_score) + sizeof(float); uint8_t* bitfield_area_ptr = after_avg_score; size_t expected_bitfield_offset = offsetof(Student, average_score) + sizeof(float); // Выравнивание до 4 байт (так как используется unsigned int) size_t aligned_offset = (expected_bitfield_offset + 3) & ~3; cout << "Расчетное смещение до битовых полей: " << expected_bitfield_offset << " байт" << endl; cout << "С учетом выравнивания: " << aligned_offset << " байт" << endl; cout << "Адрес области, содержащей битовые поля: " << static_cast(start_of_struct + aligned_offset) << endl; cout << "Размер области битовых полей: sizeof(unsigned int) = " << sizeof(unsigned int) << " байт (но используется только 1 байт)" << endl; cout << "Значение gender: " << gender_value << " (" << (gender_value ? "мужской" : "женский") << ")" << endl; cout << "Значение courses: " << courses_value << endl; // Читаем байт, содержащий битовые поля uint8_t bitfield_byte = *(start_of_struct + aligned_offset); cout << "Весь байт битовых полей в шестнадцатеричном виде: "; print_in_hex(bitfield_byte); cout << endl; cout << "Весь байт битовых полей в двоичном виде: " << bitset<8>(bitfield_byte) << endl; cout << " (бит 0: gender = " << ((bitfield_byte >> 0) & 1) << ", биты 1-7: courses = " << ((bitfield_byte >> 1) & 0x7F) << ")" << endl; cout << "\nПоле monitor:" << endl; cout << "Адрес: " << &s->monitor << endl; cout << "Смещение: " << offsetof(Student, monitor) << " байт" << endl; cout << "Размер: " << sizeof(s->monitor) << " байт" << endl; cout << "Значение: " << s->monitor << endl; cout << "Шестнадцатеричное значение: "; print_in_hex(reinterpret_cast(&s->monitor), sizeof(s->monitor)); cout << endl; cout << "Двоичное значение: " << bitset<64>(reinterpret_cast(s->monitor)) << endl; cout << "\n4. Все элементы массива в шестнадцатеричном виде:" << endl; for (int i = 0; i < 3; ++i) { cout << "\nСтудент " << i << " (\"" << students[i].name << "\"):" << endl; print_in_hex(&students[i], sizeof(Student)); if (i == 0) { cout << "\nСоответствие блоков байт полям структуры (студент 0):" << endl; // Вычисляем реальные смещения через разность адресов Student* student_ptr = &students[0]; uint8_t* base_ptr = reinterpret_cast(student_ptr); size_t name_offset = reinterpret_cast(&student_ptr->name) - base_ptr; size_t year_offset = reinterpret_cast(&student_ptr->admission_year) - base_ptr; size_t score_offset = reinterpret_cast(&student_ptr->average_score) - base_ptr; size_t monitor_offset = reinterpret_cast(&student_ptr->monitor) - base_ptr; // Для битовых полей вычисляем смещение экспериментально size_t bitfield_actual_offset = score_offset + sizeof(float); // Выравнивание до границы 4 байт bitfield_actual_offset = (bitfield_actual_offset + 3) & ~3; cout << "Байты " << name_offset << "-" << (name_offset + sizeof(student_ptr->name) - 1) << ": поле name (" << sizeof(student_ptr->name) << " байт)" << endl; cout << "Байты " << year_offset << "-" << (year_offset + sizeof(student_ptr->admission_year) - 1) << ": поле admission_year (" << sizeof(student_ptr->admission_year) << " байт)" << endl; cout << "Байты " << score_offset << "-" << (score_offset + sizeof(student_ptr->average_score) - 1) << ": поле average_score (" << sizeof(student_ptr->average_score) << " байт)" << endl; cout << "Байт " << bitfield_actual_offset << ": битовые поля gender и courses (1 байт)" << endl; cout << "Байты " << (bitfield_actual_offset + 1) << "-" << (monitor_offset - 1) << ": выравнивание (padding)" << endl; cout << "Байты " << monitor_offset << "-" << (monitor_offset + sizeof(student_ptr->monitor) - 1) << ": поле monitor (" << sizeof(student_ptr->monitor) << " байт)" << endl; cout << "\nПроверка через разность адресов:" << endl; cout << "Смещение name: " << name_offset << " байт" << endl; cout << "Смещение admission_year: " << year_offset << " байт" << endl; cout << "Смещение average_score: " << score_offset << " байт (выравнивание до 4 байт!)" << endl; cout << "Расчетное смещение битовых полей: " << bitfield_actual_offset << " байт" << endl; cout << "Смещение monitor: " << monitor_offset << " байт (выравнивание до " << alignof(Student*) << " байт!)" << endl; cout << "\nОбщий размер структуры: " << sizeof(Student) << " байт" << endl; cout << "Выравнивание структуры: " << alignof(Student) << " байт" << endl; } } } int main() { setlocale(LC_ALL, "Russian"); print_student_info(); return 0; }