Форум программистов, компьютерный форум CyberForum.ru

хитрая константа не даёт создать обычный массив - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 25, средняя оценка - 4.88
Bers
Заблокирован
25.11.2011, 18:47     хитрая константа не даёт создать обычный массив #1
Почему я не могу создать обычный массив, указав константу в качестве количества элементов?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int n=10;
const int N(n); //N вроде как константа 
                     //действительно получает значение 10
 
 
int A[N]; //error C2057: требуется константное выражение
             //error C2466: невозможно выделить память 
             //для массива постоянного нулевого размера
 
int main()
{
   int b= N; //b получает корректное значение 10
   const int c=N; //с получает корректное значение
   return 0;
};
Лучшие ответы (1)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
GhostVIRUS
 Аватар для GhostVIRUS
6 / 6 / 0
Регистрация: 17.09.2011
Сообщений: 81
25.11.2011, 21:06     хитрая константа не даёт создать обычный массив #41
Почему то я так не думаю. Т.к. для компилятора переменная - переменная, а константа - константа.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Bers
Заблокирован
25.11.2011, 21:13  [ТС]     хитрая константа не даёт создать обычный массив #42
А вот этот эксперимент наглядно показывает, что компилятор делает принципиальное различие между константами времени компиляции и всеми прочими:


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<const int Size> struct Test{  int A[Size];};
 
struct T2
{
    T2():a(333){}
    const int Get() { return a;}
    int a;
};
 
int main()
{
   T2 rrrr;
   
   Test<sizeof(int)> t; //можно
  
   Test<rrrr.Get()> t1; 
 //error C2975: Size: недопустимый аргумент шаблона для "Test", 
 //требуется константное выражение времени компиляции
   return 0;
};
Сыроежка
Заблокирован
25.11.2011, 21:21     хитрая константа не даёт создать обычный массив #43
Цитата Сообщение от Bers Посмотреть сообщение
C++
1
2
3
4
int A[100]; //живет в куче, а не на стеке.
//хотя его размер так же должен быть известен на этапе компиляции.
 
int main(){   return 0;};
Увы, вы заблуждаетесь! Этот массив не "живет" в куче. Он объявлен в статической области памяти программы, которая инициаизируется до входа в main. А память под названием куча - это совсем другое!
Bers
Заблокирован
25.11.2011, 21:23  [ТС]     хитрая константа не даёт создать обычный массив #44
Цитата Сообщение от Сыроежка Посмотреть сообщение
Увы, вы заблуждаетесь! Этот массив не "живет" в куче. Он объявлен в статической области памяти программы, которая инициаизируется до входа в main. А память под названием куча - это совсем другое!
В чем принципиальное отличие статической области памяти от кучи?
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
25.11.2011, 21:25     хитрая константа не даёт создать обычный массив #45
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Bers,
C++
1
2
3
4
int Array[100]; //живет в куче, а не на стеке.
//хотя его размер так же должен быть известен на этапе компиляции.
 
int main(){   return Array[0];};
Bash
1
2
3
alexxx@alexxx-laptop:~/c++$ g++ -g 2.cpp 
alexxx@alexxx-laptop:~/c++$ readelf -a a.out | grep Array
    59: [B]0804a040[/B]   400 OBJECT  GLOBAL DEFAULT   26 Array
Bash
1
2
alexxx@alexxx-laptop:~/c++$ objdump -d a.out > dump
alexxx@alexxx-laptop:~/c++$ less dump
Bash
1
2
3
4
5
6
7
8
08048494 <main>:
 8048494:       55                      push   %ebp
 8048495:       89 e5                   mov    %esp,%ebp
 8048497:       a1 40 a0 04 08          mov    0x804a040,%eax
 804849c:       5d                      pop    %ebp
 804849d:       c3                      ret    
 804849e:       90                      nop
 804849f:       90                      nop
в данном случае массив выделен на момент компиляции, ни о каком heap'е речь не идет
адрес массива зафиксирован за 0x804a040
подобная ситуация и для локальных статических массивов и каких-то других вариантов

второй вариант
Bash
1
2
3
4
5
6
7
8
9
alexxx@alexxx-laptop:~/c++$ cat 2.cpp
 
int main(){   
    int Array[100];
    return Array[0];
}
alexxx@alexxx-laptop:~/c++$ g++ -g 2.cpp 
alexxx@alexxx-laptop:~/c++$ readelf -a a.out | grep Array
alexxx@alexxx-laptop:~/c++$
видим, что под массив не было зарезервировано памяти

Bash
1
2
alexxx@alexxx-laptop:~/c++$ objdump -d a.out > dump
alexxx@alexxx-laptop:~/c++$ less dump
Bash
1
2
3
4
5
6
7
8
9
10
08048494 <main>:
 8048494:       55                      push   %ebp
 8048495:       89 e5                   mov    %esp,%ebp
 8048497:       81 ec 90 01 00 00       sub    $0x190,%esp
 804849d:       8b 85 70 fe ff ff       mov    -0x190(%ebp),%eax
 80484a3:       c9                      leave  
 80484a4:       c3                      ret    
 80484a5:       90                      nop
 80484a6:       90                      nop
 80484a7:       90                      nop
тут конечно какие хитрости, но видно, что массив появляется только за счет сдвига указателя стека
Сыроежка
Заблокирован
25.11.2011, 21:26     хитрая константа не даёт создать обычный массив #46
Цитата Сообщение от Bers Посмотреть сообщение
В чем принципиальное отличие статической области памяти от кучи?
Статическая память имеет фиксированный размер, которая указывается в соответствующей области образа исполнимого файла. То есть это - неотъемлемая часть самой программы. А куча - эта память, кооторую выделяет для задания менеджер заданий. Она может меняться от одного запуска до следующего запуска на одной или разных платформах. А статическая память, являющаяся частью вашей программы, всегда фиксирована, независимо от того, в какой операционной среде вы свою программу будете запускать.
Chelioss
179 / 179 / 4
Регистрация: 08.01.2011
Сообщений: 1,131
25.11.2011, 21:45     хитрая константа не даёт создать обычный массив #47
Цитата Сообщение от Сыроежка Посмотреть сообщение
То есть это - неотъемлемая часть самой программы.
А стэк? Он тоже находите в программе?
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
25.11.2011, 21:47     хитрая константа не даёт создать обычный массив #48
Цитата Сообщение от Chelioss Посмотреть сообщение
А стэк? Он тоже находите в программе?
стек это просто часть виртуальной памяти, выделенной ОС для нужд программы
адресация этой памяти идет через стековые регистры процессора ebp, esp
Сыроежка
Заблокирован
25.11.2011, 21:51     хитрая константа не даёт создать обычный массив #49
Цитата Сообщение от Chelioss Посмотреть сообщение
А стэк? Он тоже находите в программе?
Нет, стек не находится в программе. Вы лишь можете для своего модуля указать, какой максимальный размер стека ей может быть выделен менеджером программ при загрузке программы в память для выполнения. Стек не является образом программы, если только вы не пишите на ассемблере и сами туда что-то не поместили. Память, выделяемая заданию при загрузке его менеджером заданий может меняться. Например, программа может быть загружена в одну область памяти, а стек находиться в другой области памяти. Программа может, например, постоянно выгружаться из памяти компьютера во время выполнения, а стек оставться в памяти компютера. Это все зависит от архитектуры платформы.
Chelioss
179 / 179 / 4
Регистрация: 08.01.2011
Сообщений: 1,131
25.11.2011, 21:51     хитрая константа не даёт создать обычный массив #50
Цитата Сообщение от Сыроежка Посмотреть сообщение
Статическая память имеет фиксированный размер, которая указывается в соответствующей области образа исполнимого файла. То есть это - неотъемлемая часть самой программы.
C++
1
2
3
4
5
6
7
char mas[1024 * 1024 * 1024];
 
 
int main()
{
    return 0;
}
C++
1
2
3
4
int main()
{
    return 0;
}
Разницы в размере .exe, т.е. исполняемого файла, нет.
Bers
Заблокирован
25.11.2011, 21:55  [ТС]     хитрая константа не даёт создать обычный массив #51
Цитата Сообщение от alex_x_x Посмотреть сообщение
стек это просто часть виртуальной памяти, выделенной ОС для нужд программы
адресация этой памяти идет через стековые регистры процессора ebp, esp
Не дружу с ассемблером.
Но представляю себе стек, как своего рода кэш-память программы.
Она относительно маленькая, но очень быстрая.

В то время, как "природа" статической памяти и "природа" кучи мне видятся одинаковой. Ну.. не считая того, что статическая память имеет константный размер.

И если я правильно понял, то доступ к данным в куче (или к статикам) намного медленнее, чем доступ к данным на стеке.
Сыроежка
Заблокирован
25.11.2011, 21:56     хитрая константа не даёт создать обычный массив #52
Цитата Сообщение от Chelioss Посмотреть сообщение
C++
1
2
3
4
5
6
7
char mas[1024 * 1024 * 1024];
 
 
int main()
{
    return 0;
}
C++
1
2
3
4
int main()
{
    return 0;
}
Разницы в размере .exe, т.е. исполняемого файла нет.
Хороший пример! Статическая память не хранится в образе программы, если она не инициализирована каким-то значениями, отличными от 0. В образе программы хранится лишь значение объема этой памяти, которая будет выделена программе при ее загрузки, для размещения в ней статических данных программы, и будет инициализирована нулем до входа в main. Это сделано специально того, чтобы уменьшить размер загрузочного модуля. Представьте себе, если бы выхранили всю эту память, которая ничем не инициализируется в образе загрузочного модуля. Тогда бы загрузочный модель вообще не смог бы поместиться на дискету!

Но если вы свой массив проинициализируете значениями отличными от 0, то вы увидите, что размер вашего модуля увеличился!

Да, и сделайте так. чтобы мне в следующий раз было интересно вам отвечать.
Bers
Заблокирован
25.11.2011, 21:57  [ТС]     хитрая константа не даёт создать обычный массив #53
Chelioss, возможно компилятор просто выбросил неиспользованную переменную за ненадобностью. У меня в таких случаях студия варинангами ругается
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
25.11.2011, 22:00     хитрая константа не даёт создать обычный массив #54
Цитата Сообщение от Chelioss Посмотреть сообщение
Разницы в размере .exe, т.е. исполняемого файла нет.
1) массив может быть выпилен компилятором как неиспользуемый
2) для неинициализированных массивов исполняемый файл содержит лишь предписание загрузчика что где расположить
полагаю, если вы напишите char mas[1024 * 1024 * 1024] = {1,2,3,4,5,6,7,8,9,10};
размер изменится
Bers
Заблокирован
25.11.2011, 22:09  [ТС]     хитрая константа не даёт создать обычный массив #55
Цитата Сообщение от Сыроежка Посмотреть сообщение
Да, и сделайте так. чтобы мне в следующий раз было интересно вам отвечать
Из ваших ответов можно сделать одно очень смелое предположение:



C++
1
2
3
4
5
6
7
8
9
int b=100;
int main()
{
    int a=100;
    std::cout<< "Adress a= "<<&a<<std::endl;
    std::cout<< "Adress b= "<<&b<<std::endl;
 
   return 0;
};
Запускайте эту программку несколько раз. Обратите внимание на показания.
Адрес глобальной переменной не меняется

Я полагаю, объяснить это явление можно так: программа имеет фиксированный размер статической памяти. Причем этот размер формируется специально для того, что бы расположить в ней все глобал-статики данные, размеры которых известны на стадии компиляции.

Другими словами, все глобал-статики всегда размещаются по одним и тем же адресам.
И эти адреса не меняются от запуска к запуску программы.
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
25.11.2011, 22:13     хитрая константа не даёт создать обычный массив #56
Цитата Сообщение от Bers Посмотреть сообщение
И если я правильно понял, то доступ к данным в куче (или к статикам) намного медленнее, чем доступ к данным на стеке.
да
чтобы расположить данные на стеке надо сдвинуть пару регистров в процессоре (ясное дело что с виртуальной памятью и защищенным режимом свои усложнения, но в целом все просто)
просить памяти у ос не надо, так как она предварительно выделена в некотором количестве (при приближении к вершине стека может быть выделено еще, в каждой ос свои способы)
адресация относительная - адреса выделяются по нарастающей - выделение и отдача памяти элементарная и быстрая
проблема в том, что время жизни выделенной памяти жестко фиксировано стеком вызовов - поэтому такой способ выделения данных работает только для локальных переменных

куча же пользуясь системными вызовами запрашивает у ОС память - у стека она уже выделена при старте программы
кроме того менеджеру памяти постоянно приходится сталкиватся с фрагментацией и думать куда бы приткнуть данные пользователя
естественно логика его работы значительно сложней

Добавлено через 2 минуты
Цитата Сообщение от Bers Посмотреть сообщение
Другими словами, все глобал-статики всегда размещаются по одним и тем же адресам.
И эти адреса не меняются от запуска к запуску программы.
зависит от работы компилятора
да и вообще, во всех топовых компиляторах есть http://en.wikipedia.org/wiki/Address..._randomization
Bers
Заблокирован
25.11.2011, 22:13  [ТС]     хитрая константа не даёт создать обычный массив #57
alex_x_x, Да понятно, что выделять память на куче дольше.
Речь о самом доступе к данным. Само обращение к данным, которые живут на куче дольше, чем обращение к данным, которые живут на стеке
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
25.11.2011, 22:15     хитрая константа не даёт создать обычный массив #58
Bers, без разницы - виртуальная память одна, что для кучи, что для стека, что для статических и глобальных данных
Bers
Заблокирован
25.11.2011, 22:17  [ТС]     хитрая константа не даёт создать обычный массив #59
Цитата Сообщение от alex_x_x Посмотреть сообщение
Bers, без разницы - виртуальная память одна, что для кучи, что для стека, что для статических и глобальных данных
Значит, если объекты уже созданы, то скорость работы с ними одинаковая; не зависит от того, где эти объекты живут: на стеке, или в куче?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.11.2011, 22:21     хитрая константа не даёт создать обычный массив
Еще ссылки по теме:

C++ Скопировать элементы Vector в обычный массив
Константа Пи в С++ C++
Можно ли создать проект не managed c++, а обычный c++, но с формами в VS2008? C++

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

Или воспользуйтесь поиском по форуму:
Chelioss
179 / 179 / 4
Регистрация: 08.01.2011
Сообщений: 1,131
25.11.2011, 22:21     хитрая константа не даёт создать обычный массив #60
Цитата Сообщение от alex_x_x Посмотреть сообщение
просить памяти у ос не надо, так как она предварительно выделена в некотором количестве (при приближении к вершине стека может быть выделено еще, в каждой ос свои способы)
Т.е. программа владеет стековой памятью полностью, а кучой как бы и владеет, но не владеет. Не владеет в том, что памятью управляет менеджер памяти, а программа лишь запрашивает память. Владеет в том, что память отведена для именно этой программы и никакой больше.
Так?
Yandex
Объявления
25.11.2011, 22:21     хитрая константа не даёт создать обычный массив
Ответ Создать тему
Опции темы

Текущее время: 22:49. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru