Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 16, средняя оценка - 4.94
Lers
13 / 13 / 3
Регистрация: 27.05.2012
Сообщений: 208
#1

Как происходит процесс выделения памяти в стеке и куче - C++

16.01.2014, 14:46. Просмотров 2562. Ответов 48
Метки нет (Все метки)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include "disc.h"
void main()
{
  SetConsoleCP(1251);
  SetConsoleOutputCP(1251);
  
  Disc d1,d2[2];
  Disc *d3,*d4;
  d3=new Disc;
  int kol=0,n;
  clrscr();
  kol++;
  printf("%i)",kol);
  printf("\nВведите название дисциплины -> ");
  gets(d1.namedisc);
  printf("Введите имя перподавателя -> ");
  gets(d1.teacher_name);
  printf("Введите название группы -> ");
  gets(d1.name_group);
  printf("Введите кол-во часов на изуч. дисциплины-> ");
  scanf("%i",&d1.hours);
  fflush(stdin);
  
  for (int i=0; i<1; i++)
  {
    clrscr();
    kol++;
    printf("%i)",kol);
    printf("\nВведите название дисциплины -> ");
    gets(d2[i].namedisc);
    printf("Введите имя перподавателя -> ");
    gets(d2[i].teacher_name);
    printf("Введите название группы -> ");
    gets(d2[i].name_group);
    printf("Введите кол-во часов на изуч. дисциплины-> ");
    scanf("%i",&d2[i].hours);
    fflush(stdin);
  }
 
  clrscr();
  kol++;
  printf("%i)",kol);
  printf("\nВведите название дисциплины -> ");
  gets(d3->namedisc);
  printf("Введите имя перподавателя -> ");
  gets(d3->teacher_name);
  printf("Введите название группы -> ");
  gets(d3->name_group);
  printf("Введите кол-во часов на изуч. дисциплины-> ");
  scanf("%i",&d3->hours);
  fflush(stdin);
 
  printf ("\n Введите кол-во записей-> ");
  scanf ("%i",&n);
  d4=new Disc [n];
  fflush(stdin);
  for (int i=0; i<n; i++)
  {
    clrscr();
    kol++;
    printf("%i)",kol);
    printf("\nВведите название дисциплины -> ");
    gets(d4[i].namedisc);
    printf("Введите имя перподавателя -> ");
    gets(d4[i].teacher_name);
    printf("Введите название группы -> ");
    gets(d4[i].name_group);
    printf("Введите кол-во часов на изуч. дисциплины-> ");
    scanf("%i",&d4[i].hours);
    fflush(stdin);
  }
  clrscr();
  kol=0;
  printf("\n------------------------------------------------------------");
  printf("\n|№|Название дисциплины |Имя преподавателя   |Имя группы|Час|");
  printf("\n------------------------------------------------------------");
  kol++;
  printf("\n|%1i|%20s|%20s|%10s|%3i|",kol,d1.namedisc,d1.teacher_name,d1.name_group,d1.hours);
  for (int i=0; i<1; i++)
    printf("\n|%1i|%20s|%20s|%10s|%3i|",kol+i+1,d2[i].namedisc,d2[i].teacher_name,d2[i].name_group,d2[i].hours);
  kol+=3;
   printf("\n|%1i|%20s|%20s|%10s|%3i|",kol,d3->namedisc,d3->teacher_name,d3->name_group,d3->hours);
  for (int i=0; i<n; i++)
    printf("\n|%1i|%20s|%20s|%10s|%3i|",kol+i+1,d4[i].namedisc,d4[i].teacher_name,d4[i].name_group,d4[i].hours);
  kol+=2;  
  printf("\n------------------------------------------------------------");
  getch();
  delete d3;
  delete []d4;
}
C++
1
2
3
4
5
6
7
8
class Disc
{
  public:
  char namedisc[20];
  char teacher_name[20];
  char name_group[10];
  int hours;
};
Тут я просто вывожу в табличке свой класс, просто 4 способами, через переменную, массив, указатель и дин.массив. Вопрос вот выделении памяти под объекты класса (d1,d2[i],*d3,*d4);
писал sizeof для каждого объекта и получил что
d1=56 байта (тут вроде 3 chara 20+20+10+ 1 int=4 байтам=54 байта, куда выделяются еще 2 байта?)
d2=112 байта (ну тут понятно, что записей в массиве 2, 56+56=112)
d3=4 байта (тут 4 байта при записи sizeof(d3)-т.е. на каждое поле класса, их всего 4 выделяется по 1 байту?)
(а если написать sizeof(*d3) то будет снова 56 байт
d4=4 байта (тут аналогично)
Объясните пожалуйста, как происходит процесс выделения памяти в стеке и куче, ну и про кол-во байтов на объекты класса.
Все это делаю в C++ Builder 6
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.01.2014, 14:46
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Как происходит процесс выделения памяти в стеке и куче (C++):

Как выделяется память на стеке и на куче? Когда нужна ручная очистка? - C++
Всем здрасьте. //1 char s = 's'; //2 char* ss = new char; Во втором случае компилятор выделяет участок памяти, потом мне же её...

Расположение данных в стеке и в куче - C++
Друзья, возник вопрос. Следующий код char length_buffer; ...заполнение length_buffer двоичным представлением целого числа 999... ...

Не могу понять где объект в куче или в стеке ! - C++
Сразу к примеру: class Zombie; { Soldat soldat; // что солдат внутри зомби делает не спрашивайте String name; int ...

Указатели (Выделение памяти в куче) - C++
Чтобы создать в динамически распределяемой памяти переменную типа unsigned short необходимо написать следующее: unsigned short...

Потоки и выделение памяти в куче - C++
Подскажите, кто знает, какие есть тонкости при выделении памяти в куче (new) в потоках отличных от главного. У меня возникают исключения...

Как написать программу для динамического выделения памяти с использованием new - C++
Надо написать прогу, которая выделяет память для структур размером в 2048 байт и обрабатывает ситуацию в случае ее нехватки. Я понятия не...

48
Lers
13 / 13 / 3
Регистрация: 27.05.2012
Сообщений: 208
16.01.2014, 18:20  [ТС] #16
Еще вопрос возник, в моем варианте программы, в стеке хранятся данные объекты d1,d2 и адреса на объекта указателей *d3, *d4.
В куче храниться только данные объектов d3,d4 или чего еще?
Где хранятся адреса объектов d1,d2? Тоже в стеке?
т.е. когда вот такая запись gets((&d1)->namedisc); то я обращаюсь в стек за адресом объекта
а когда такая (*d3).namedisc; то я обращаюсь в кучу за объектом?

P.S. извиняюсь за неугомонность
0
alsav22
5436 / 4831 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
16.01.2014, 18:54 #17
Цитата Сообщение от Lers Посмотреть сообщение
Где хранятся адреса объектов d1,d2? Тоже в стеке?
Нигде. При определении переменной под неё выделяется память, адрес которой связан с именем данной переменной (именованная область памяти). Для локальных переменных d1, d2, d3(указатель), d4(указатель) память выделяется на стеке, на этапе компиляции, и адреса этой памяти связаны с именами этих переменных. Чтобы получиь эти адреса, нужно применить к именам переменных операцию взятия адреса: &. В динамческой памяти, память под переменные выделяется неименованная (выделяется в процессе работы программы). Поэтому доступ к таким переменным возможен только через адреса (указатели).
Цитата Сообщение от Lers Посмотреть сообщение
т.е. когда вот такая запись gets((&d1)->namedisc); то я обращаюсь в стек за адресом объекта
Обращаетесь к полю объекта, через его адрес на стеке.
Цитата Сообщение от Lers Посмотреть сообщение
а когда такая (*d3).namedisc; то я обращаюсь в кучу за объектом?
Обращаетесь к полю объекта, через объект, получаемый разыменованием указателя на объект.
1
Lers
13 / 13 / 3
Регистрация: 27.05.2012
Сообщений: 208
16.01.2014, 19:04  [ТС] #18
alsav22, (*d3).namedisc; Обращаюсь к полю объекта, через объект, получаемый разыменованием указателя на объект, это я понял, а обращаюсь я же в стек?
0
alsav22
5436 / 4831 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
16.01.2014, 19:21 #19
Цитата Сообщение от Lers Посмотреть сообщение
В куче храниться только данные объектов d3,d4 или чего еще?
Нельзя сказать, что в куче хранятся объекты d3, d4, т.к. объекты в куче неименованные. В указателях d3, d4 хранятся адреса объектов в куче.

Добавлено через 9 минут
Цитата Сообщение от Lers Посмотреть сообщение
(*d3).namedisc; Обращаюсь к полю объекта, через объект, получаемый разыменованием указателя на объект, это я понял, а обращаюсь я же в стек?
Чтобы получить адрес объекта, да (указатель же на стеке создан). А для получения поля объекта - обращаетесь в кучу (там же сам неименовынный объект находится, по адресу, взятому из указателя). Вообще, как не пиши, просто имя объекта или указатель на объект, всё, в конечном счёте, сводится к адресам. В одних случаях имя объекта - адрес, в других случаях значение указателя адрес. Вот такая запись: (*d3).namedisc - некое извращение. В результате всё равно будет получен адрес в куче. Если уж d3 указатель, то нужно использовать синтаксис указателя: d3 ->namedisc, чтобы не было лишней путаницы.

Добавлено через 7 минут
Вот это тоже - некое извращение:
C++
1
(&d1) ->namedisc;
Адрес берётся только для того, чтобы обратиться к полю через оператор косвенной адресации.
1
Lers
13 / 13 / 3
Регистрация: 27.05.2012
Сообщений: 208
16.01.2014, 19:32  [ТС] #20
alsav22, это не моя прихоть так извращаться
Спасибо большое за помощь!
0
alsav22
5436 / 4831 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
16.01.2014, 19:35 #21
Цитата Сообщение от Lers Посмотреть сообщение
это не моя прихоть так извращаться
А чья? Кто-то заставляет так писать?
0
Lers
13 / 13 / 3
Регистрация: 27.05.2012
Сообщений: 208
16.01.2014, 19:51  [ТС] #22
Цитата Сообщение от alsav22 Посмотреть сообщение
А чья? Кто-то заставляет так писать?
Преподы издеваются, говорят если знаешь эти извращение, то имеешь понятие о выделение памяти в стеке, куче и т.п..

Добавлено через 2 минуты
Мм забыл про выравнивание....
Немного потестил сколько выделяется памяти на выравнивание типа int,double,long double
1) при int выделяется 2 байта на вырав.
2) при double 6 байт
3) при long double 12 байтов
Искал инфу про выравнивание написанное доступным языком, толкового не нашел.
Может кто знает, расскажите пожалуйста
0
ValeryS
Модератор
6969 / 5306 / 522
Регистрация: 14.02.2011
Сообщений: 17,889
16.01.2014, 20:11 #23
Цитата Сообщение от Lers Посмотреть сообщение
Преподы издеваются, говорят если знаешь эти извращение, то имеешь понятие о выделение памяти в стеке, куче и т.п..
спроси у них
в таком коде
C++
1
2
3
void fnc(int a)
{
 int b
где разместятся a и b для процессоров( микроконтроллеров)
таких как Intel 8051 или Atmega8535
если ответят в стеке то можешь смело их посылать....... учится
нет там таких размеров стеков, в регистрах будут размешатся
и даже всеми любимяй 80х86 может спокойно расположить локальную переменную не в стеке а в регистрах
так что эти извраты не приведут тебя к пониманию

Добавлено через 7 минут
Цитата Сообщение от Lers Посмотреть сообщение
Мм забыл про выравнивание....
зависит от процессора и от настроек компилятора
выравнивание удобно процессору чтобы быстрее иметь доступ
так
8 битные процессоры будут выравнивать на на границу байта( отсутствует выравнивание)
16 битные на границу двух байтов
32 битные на границу четырех байтов
64 битные на границу 8 байтов
так адреса в структуре
C++
1
2
3
4
5
struct aa
{
char c;
int i;
}
могут быть
для 8 битного
c 0х00;
i 0х01;
для 16 битного
c 0х00;
i 0х02;
для 32 битного
c 0х00;
i 0х04;
для 64 битного
c 0х00;
i 0х08;

не знаю понятно ли объяснил?

Добавлено через 6 минут
Цитата Сообщение от Lers Посмотреть сообщение
при int выделяется 2 байта на вырав.
размер int 4 байта для 32 разрядных и 2 байта у 16 битных
размер int чаще всего привязан к разрядности процессора
Цитата Сообщение от Lers Посмотреть сообщение
при double 6 байт
размер double 8 байт
Цитата Сообщение от Lers Посмотреть сообщение
при long double 12 байтов
размер long double 10 байт ( правда микрософт на это плюет и размер long double у него тоже 8 байт)
для проверки размера существует sizeof возвращает размер в байтах
но никакого отношения размер переменных к выравниванию не имеет
1
Lers
13 / 13 / 3
Регистрация: 27.05.2012
Сообщений: 208
16.01.2014, 20:15  [ТС] #24
Залил картинку настроек билдера своего, я так понимаю то, что я выделил и есть настройка выравнивания?
мля ссылку не хочет вставлять.

Data aligment-> Quad word это выравнивание?

Добавлено через 3 минуты
Цитата Сообщение от ValeryS Посмотреть сообщение

размер int 4 байта для 32 разрядных и 2 байта у 16 битных
размер int чаще всего привязан к разрядности процессора

размер double 8 байт

размер long double 10 байт ( правда микрософт на это плюет и размер long double у него тоже 8 байт)
для проверки размера существует sizeof возвращает размер в байтах
но никакого отношения размер переменных к выравниванию не имеет
то что размер double 8 байт я знаю, в моей программе при использование double вместо int выделяется 6 байт на выравнивает и 12 байт при long double
0
ValeryS
Модератор
6969 / 5306 / 522
Регистрация: 14.02.2011
Сообщений: 17,889
16.01.2014, 20:15 #25
Цитата Сообщение от Lers Посмотреть сообщение
мля ссылку не хочет вставлять
залей картинку
расширенный режим значок скрепки
правда я в Билдере не очень последний раз общался с продукцией Borland еще под DOS на BC3.1
0
alsav22
16.01.2014, 20:16
  #26

Не по теме:

Цитата Сообщение от Lers Посмотреть сообщение
Преподы издеваются, говорят если знаешь эти извращение, то имеешь понятие о выделение памяти в стеке, куче и т.п..
Такие извращения не относятся к понятиям. Есть понятия, суть, и есть синтаксис. Синтаксис позовляет одно и тоже записать самыми разными способами. Одни способы привычны, понятны, рациональны, другие - наоборот.

0
Lers
13 / 13 / 3
Регистрация: 27.05.2012
Сообщений: 208
16.01.2014, 20:18  [ТС] #27
Как происходит процесс выделения памяти в стеке и куче
0
Lers
13 / 13 / 3
Регистрация: 27.05.2012
Сообщений: 208
16.01.2014, 20:27  [ТС] #28
Byte — 8 бит
Word — 16 бит
Double Word — 32 бит
Quad Word — 64 бит
Octa Word — 128 бит
0
ValeryS
Модератор
6969 / 5306 / 522
Регистрация: 14.02.2011
Сообщений: 17,889
16.01.2014, 20:31 #29
Цитата Сообщение от Lers Посмотреть сообщение
то что размер double 8 байт я знаю, в моей программе при использование double вместо int выделяется 6 байт на выравнивает и 12 байт при long double
а как узнал то?
и программа то эта?
Цитата Сообщение от Lers Посмотреть сообщение
class Disc
{
* public:
* char namedisc[20];
* char teacher_name[20];
* char name_group[10];
* int hours;
};
можешь сам посмотреть куда лягут переменные при разных режимах выравнивания и даже если поменяешь между собой члены
C++
1
2
3
4
5
6
7
8
9
10
11
Disc D;
void *addr=(void)&D;
void *addr_namedisc=(void)&D.namedisc[0];
void *addr_teacher_name=(void)&D.teacher_name[0];
void *addr_group=(void)&D_group[0];
void *addr_hours=(void)&D.hours;
print("offset namedisc=%x, offset teacher_name= %x offset name_group= %x offset hours=%x",
       addr_namedisc-addr,
       addr_teacher_name-addr,
       addr_group-addr,
       addr_hours-addr);
Добавлено через 1 минуту
Lers, судя по картинке у тебя выравнивание на 8 бит ( счетвереннное слово, а слово это два байта)
0
Lers
13 / 13 / 3
Регистрация: 27.05.2012
Сообщений: 208
16.01.2014, 20:36  [ТС] #30
ValeryS, да класс этот, sizeof и проверял.
т.е. 3 char,1 int =56
3 char, 1 long double=72
3 char, 1 double=64

Добавлено через 53 секунды
может на 8 байт?

Добавлено через 2 минуты
а может быть такое, что билдер растягивает размер для того чтобы размер был кратен 8 ( т.е. выравниванию)
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.01.2014, 20:36
Привет! Вот еще темы с ответами:

Динамическое выделение памяти. Ошибки в куче - C++
Функция чтения данных из ячейки экселя wchar_t *DataInCell( Excel::_WorksheetPtr Sheet, int Row, int Col ) Excel::RangePtr Cell; ...

Нужно перевести из С++ в C строку с выделением памяти в куче - C++
Есть функция, для определения...что ли длинны записанного в файле. int length() { int len=0; Node tmp; ...

Выделение памяти на стеке - C++
Добрый день. Часто в учебниках и на форуме я встречал такое выражение как &quot;переменная создаётся в (или на) стеке&quot;. Мне непонятно, что это...

Нужно ли удалять указатель на символьный массив созданный в куче(динамически распределяемой памяти) - C++
Подскажите, программа состоит из 2 функций (main и fun), программа меняет значение указателя на символьный массив созданный в динамически...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru