Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.56/41: Рейтинг темы: голосов - 41, средняя оценка - 4.56
Заблокирован

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

25.11.2011, 18:47. Показов 8752. Ответов 64
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Почему я не могу создать обычный массив, указав константу в качестве количества элементов?

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;
};
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
25.11.2011, 18:47
Ответы с готовыми решениями:

Даны функциональная константа, предикатная константа и определённое количество аксиом. Как построить модель
Даны функциональная константа, предикатная константа и определённое количество аксиом. Как построит модель?

Сервер 2008R2- даёт IP 192.168.0.(2-200), и даёт неправильные DNS сервера
Сервер 2008 R2- даёт IP adress например 192.168.0.(2-200), и над значоком интернета восклицательный значок есть без доступа к интернету...

Модем (роутер) не даёт авторизоваться на некоторых сайтах, а также не даёт зарегистрировать антивирус
Здравствуйте! У меня такая ситуация. Обратилась ко мне знакомая - компьютер заблокировался (порнобаннер). Ну, я взял её комп и первым...

64
 Аватар для GhostVIRUS
6 / 6 / 0
Регистрация: 17.09.2011
Сообщений: 81
25.11.2011, 21:06
Студворк — интернет-сервис помощи студентам
Почему то я так не думаю. Т.к. для компилятора переменная - переменная, а константа - константа.
1
Заблокирован
25.11.2011, 21:13  [ТС]
А вот этот эксперимент наглядно показывает, что компилятор делает принципиальное различие между константами времени компиляции и всеми прочими:


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;
};
0
Заблокирован
25.11.2011, 21:21
Цитата Сообщение от Bers Посмотреть сообщение
C++
1
2
3
4
int A[100]; //живет в куче, а не на стеке.
//хотя его размер так же должен быть известен на этапе компиляции.
 
int main(){   return 0;};
Увы, вы заблуждаетесь! Этот массив не "живет" в куче. Он объявлен в статической области памяти программы, которая инициаизируется до входа в main. А память под названием куча - это совсем другое!
1
Заблокирован
25.11.2011, 21:23  [ТС]
Цитата Сообщение от Сыроежка Посмотреть сообщение
Увы, вы заблуждаетесь! Этот массив не "живет" в куче. Он объявлен в статической области памяти программы, которая инициаизируется до входа в main. А память под названием куча - это совсем другое!
В чем принципиальное отличие статической области памяти от кучи?
1
бжни
 Аватар для alex_x_x
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
25.11.2011, 21:25
Лучший ответ Сообщение было отмечено как решение

Решение

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
тут конечно какие хитрости, но видно, что массив появляется только за счет сдвига указателя стека
3
Заблокирован
25.11.2011, 21:26
Цитата Сообщение от Bers Посмотреть сообщение
В чем принципиальное отличие статической области памяти от кучи?
Статическая память имеет фиксированный размер, которая указывается в соответствующей области образа исполнимого файла. То есть это - неотъемлемая часть самой программы. А куча - эта память, кооторую выделяет для задания менеджер заданий. Она может меняться от одного запуска до следующего запуска на одной или разных платформах. А статическая память, являющаяся частью вашей программы, всегда фиксирована, независимо от того, в какой операционной среде вы свою программу будете запускать.
2
186 / 186 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
25.11.2011, 21:45
Цитата Сообщение от Сыроежка Посмотреть сообщение
То есть это - неотъемлемая часть самой программы.
А стэк? Он тоже находите в программе?
0
бжни
 Аватар для alex_x_x
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
25.11.2011, 21:47
Цитата Сообщение от Chelioss Посмотреть сообщение
А стэк? Он тоже находите в программе?
стек это просто часть виртуальной памяти, выделенной ОС для нужд программы
адресация этой памяти идет через стековые регистры процессора ebp, esp
1
186 / 186 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
25.11.2011, 21:51
Цитата Сообщение от Сыроежка Посмотреть сообщение
Статическая память имеет фиксированный размер, которая указывается в соответствующей области образа исполнимого файла. То есть это - неотъемлемая часть самой программы.
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
Заблокирован
25.11.2011, 21:51
Цитата Сообщение от Chelioss Посмотреть сообщение
А стэк? Он тоже находите в программе?
Нет, стек не находится в программе. Вы лишь можете для своего модуля указать, какой максимальный размер стека ей может быть выделен менеджером программ при загрузке программы в память для выполнения. Стек не является образом программы, если только вы не пишите на ассемблере и сами туда что-то не поместили. Память, выделяемая заданию при загрузке его менеджером заданий может меняться. Например, программа может быть загружена в одну область памяти, а стек находиться в другой области памяти. Программа может, например, постоянно выгружаться из памяти компьютера во время выполнения, а стек оставться в памяти компютера. Это все зависит от архитектуры платформы.
1
Заблокирован
25.11.2011, 21:55  [ТС]
Цитата Сообщение от alex_x_x Посмотреть сообщение
стек это просто часть виртуальной памяти, выделенной ОС для нужд программы
адресация этой памяти идет через стековые регистры процессора ebp, esp
Не дружу с ассемблером.
Но представляю себе стек, как своего рода кэш-память программы.
Она относительно маленькая, но очень быстрая.

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

И если я правильно понял, то доступ к данным в куче (или к статикам) намного медленнее, чем доступ к данным на стеке.
0
Заблокирован
25.11.2011, 21:56
Цитата Сообщение от 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, то вы увидите, что размер вашего модуля увеличился!

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



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;
};
Запускайте эту программку несколько раз. Обратите внимание на показания.
Адрес глобальной переменной не меняется

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

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

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

Добавлено через 2 минуты
Цитата Сообщение от Bers Посмотреть сообщение
Другими словами, все глобал-статики всегда размещаются по одним и тем же адресам.
И эти адреса не меняются от запуска к запуску программы.
зависит от работы компилятора
да и вообще, во всех топовых компиляторах есть http://en.wikipedia.org/wiki/A... domization
0
Заблокирован
25.11.2011, 22:13  [ТС]
alex_x_x, Да понятно, что выделять память на куче дольше.
Речь о самом доступе к данным. Само обращение к данным, которые живут на куче дольше, чем обращение к данным, которые живут на стеке
0
бжни
 Аватар для alex_x_x
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
25.11.2011, 22:15
Bers, без разницы - виртуальная память одна, что для кучи, что для стека, что для статических и глобальных данных
0
Заблокирован
25.11.2011, 22:17  [ТС]
Цитата Сообщение от alex_x_x Посмотреть сообщение
Bers, без разницы - виртуальная память одна, что для кучи, что для стека, что для статических и глобальных данных
Значит, если объекты уже созданы, то скорость работы с ними одинаковая; не зависит от того, где эти объекты живут: на стеке, или в куче?
0
186 / 186 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
25.11.2011, 22:21
Цитата Сообщение от alex_x_x Посмотреть сообщение
просить памяти у ос не надо, так как она предварительно выделена в некотором количестве (при приближении к вершине стека может быть выделено еще, в каждой ос свои способы)
Т.е. программа владеет стековой памятью полностью, а кучой как бы и владеет, но не владеет. Не владеет в том, что памятью управляет менеджер памяти, а программа лишь запрашивает память. Владеет в том, что память отведена для именно этой программы и никакой больше.
Так?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
25.11.2011, 22:21
Помогаю со студенческими работами здесь

Массив-константа
Имеются некоторые массивы-константы типа string, описанные в начале программы. Program Rec17; uses crt,dos; const {блаблабла} ...

Почему ссылка с именем умной таблицы в ячейке не даёт ссылку на эту таблицу в формуле, а имя текстом даёт?
В общем, пытаюсь сделать зависимый список используя именно формулы и проверку данных. И тут столкнулся со странной штукой, оказывается,...

Не даёт создать функцию с двумерным массивом
Делаю задание 1.17 из Керниган, Ричи там где нужно создать программу которая бы выводила все строки длиннее определенной длинны. Создал для...

Static массив не даёт выполнить запись
Здравствуйте. Есть инициализация массива: private static Object object = new Object; Пытаюсь выполнить запись в массив(вызвать методы...

как создать самый обычный сайт
Где будет: 1: Главная, ну и еще пару страниц. 2: Самое главное для сайта и для меня - ВХОД И РЕГИСТРАЦИЯ. Запрет на некоторые...


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

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru