Вы не можете выбрать более 25 тем
Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
219 строки
11 KiB
C++
219 строки
11 KiB
C++
#define _CRT_SECURE_NO_WARNINGS
|
|
|
|
#include <iostream>
|
|
#include <cstdint>
|
|
#include <cstddef>
|
|
#include <cstring>
|
|
#include <bitset>
|
|
|
|
using namespace std;
|
|
|
|
void print_in_hex(const void* data, size_t size)
|
|
{
|
|
const uint8_t* bytes = static_cast<const uint8_t*>(data);
|
|
for (size_t i = 0; i < size; ++i)
|
|
{
|
|
cout << hex << uppercase << static_cast<int>(bytes[i] / 16)
|
|
<< static_cast<int>(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<int>(byte / 16)
|
|
<< static_cast<int>(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<void*>(&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<const uint8_t*>(&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<const uint8_t*>(&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<uint8_t*>(s);
|
|
uint8_t* after_avg_score = reinterpret_cast<uint8_t*>(&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<void*>(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<const uint8_t*>(&s->monitor), sizeof(s->monitor));
|
|
cout << endl;
|
|
cout << "Двоичное значение: " << bitset<64>(reinterpret_cast<uint64_t>(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<uint8_t*>(student_ptr);
|
|
|
|
size_t name_offset = reinterpret_cast<uint8_t*>(&student_ptr->name) - base_ptr;
|
|
size_t year_offset = reinterpret_cast<uint8_t*>(&student_ptr->admission_year) - base_ptr;
|
|
size_t score_offset = reinterpret_cast<uint8_t*>(&student_ptr->average_score) - base_ptr;
|
|
size_t monitor_offset = reinterpret_cast<uint8_t*>(&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;
|
|
} |