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

Почему это компилируется, ведь под второй массив по идее не выделено в куче памяти

11.09.2014, 23:38. Показов 1049. Ответов 15
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
К сожалению на момент создания темы исходника не было под рукой...В общем что значит вот такой способ инициации двухмерного массива:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int A,B
cin>>A;cin>>B;
double** BlockField_memory= new double* [A];
for(int a=0;a<A;a++)
    {
 BlockField_memory[a]=new double[B];
    }
double BlockField[A][B];
*действия с BlockField[A][B]*
for(int a=0;a<A;a++)
    {
delete BlockField_memory[A];
    }
delete[] BlockField_memory;
Странно, не так ли? А теперь внимание- это компилируется и работает! С такой матрицей можно что угодно делать, сам проверял. Наткнулся на такое в чужом коде, стало любопытно. Зачем переобъявлять массив еще раз? Почему это компилируется, ведь под второй массив по идее не выделено в куче памяти Оо?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
11.09.2014, 23:38
Ответы с готовыми решениями:

По идее не должно компилироваться, но компилируется. Почему?
здравствуйте, подскажите, почему компилируется конструкция: BOOST_MPL_ASSERT((boost::mpl::equal&lt;boost::variant&lt;int, double&gt;, ...

В массив записывается больше, чем было выделено памяти
Я выделил 10 байт для хранения массива типа char, но я могу в него записать почему-то больше значений. Менял RAZM на 20 и даже на 2000 и...

Компилируется то, что по идее не должно
Недавно писал программмку и наткнулся на очень интересную вешь: #include &lt;iostream&gt; using namespace std; int main() { ...

15
 Аватар для IrineK
2023 / 1641 / 425
Регистрация: 23.02.2011
Сообщений: 6,002
Записей в блоге: 25
12.09.2014, 00:07
Цитата Сообщение от FulcrumPlus Посмотреть сообщение
Зачем переобъявлять массив еще раз?
Один называется
Цитата Сообщение от FulcrumPlus Посмотреть сообщение
BlockField_memory
второй
Цитата Сообщение от FulcrumPlus Посмотреть сообщение
BlockField
Где переобъявление?
0
 Аватар для contedevel
57 / 55 / 13
Регистрация: 07.10.2012
Сообщений: 606
12.09.2014, 00:17
Цитата Сообщение от FulcrumPlus Посмотреть сообщение
C++
1
double** BlockField_memory= new double* [A];
В общем не уловил фишки со вторым массивом (да и с первым тоже)
Но первый массив - это просто динамически созданный одномерный массив указателей, то есть каждый его элемент ссылается на динамический массив размерности B, хотя может ссылаться даже просто на переменную или массивы разных размерностей или иметь нулевой указатель
0
5499 / 4894 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
12.09.2014, 00:25
Цитата Сообщение от FulcrumPlus Посмотреть сообщение
А теперь внимание- это компилируется
Нет. В первой строке точка с запятой забыты. В студии вот эта строка не пройдёт (по стандарту, размерность, статически создаваемого массива, должна быть константной):
C++
1
double BlockField[A][B];
Цитата Сообщение от FulcrumPlus Посмотреть сообщение
и работает!
Нет, у меня виснет. Освождение памяти неверное, в 12 строке нужно:
C++
1
delete [] BlockField_memory[a];
0
 Аватар для contedevel
57 / 55 / 13
Регистрация: 07.10.2012
Сообщений: 606
12.09.2014, 00:26

Не по теме:

Блин, что-то сразу не въехал


Второй массив скорее всего на стадии компиляции в динамический преобразуется, сейчас попробую точно посмотреть, но это должно от компилятора зависеть, сам язык такого не должен позволять
0
Эксперт PHP
 Аватар для Kerry_Jr
3106 / 2591 / 1219
Регистрация: 14.05.2014
Сообщений: 7,236
Записей в блоге: 1
12.09.2014, 00:32
У меня MinGW 4.8.1, и такой код
C++
1
2
3
int a;
cin >> a;
int b[a];
спокойно компилируется без каких-либо проблем.
0
Модератор
Эксперт по электронике
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,852
12.09.2014, 00:38
Цитата Сообщение от FulcrumPlus Посмотреть сообщение
Странно, не так ли?
а что странного?
нет такого понятия двумерный массив при динамике, есть массив указателей,можно с большой натяжкой назвать массив массивов
Цитата Сообщение от FulcrumPlus Посмотреть сообщение
C++
1
double** BlockField_memory= new double* [A];
выделяем массив указателей на тип double
Цитата Сообщение от FulcrumPlus Посмотреть сообщение
C++
1
2
3
4
for(int a=0;a<A;a++)
    {
 BlockField_memory[a]=new double[B];
    }
каждому указателю присваиваем значения выделенной памяти под одномерный массив double
и не факт что они будут лежать рядом это не статика
типа
C++
1
2
double a[2][2];
a[0][2]=5;// по факту запишем в a[1][1]=5
с динамикой такое не пройдет, как минимум исключение неправомерный доступ
про все остальное alsav22, сказал

Добавлено через 1 минуту
Цитата Сообщение от Kerry_Jr Посмотреть сообщение
У меня MinGW 4.8.1, и такой код
и что???
стандарт открой и посмотри
а то что GNUс ведет себя не по стандарту это всем давно известно
0
5499 / 4894 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
12.09.2014, 00:38
Цитата Сообщение от Kerry_Jr Посмотреть сообщение
спокойно компилируется без каких-либо проблем
Солтер Н.А., Клепер С.Дж. "С++ для профессионалов".
Миниатюры
Почему это компилируется, ведь под второй массив по идее не выделено в куче памяти  
0
 Аватар для contedevel
57 / 55 / 13
Регистрация: 07.10.2012
Сообщений: 606
12.09.2014, 00:50
Вот дизассемблированный код с исходным в перемешку, думаю, наглядно показывает, как компилятор преобразует код
Assembler
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
94
6   {
0x4007dd    push   rbp
0x4007de    mov    rbp,rsp
0x4007e1    push   r15
0x4007e3    push   r14
0x4007e5    push   r13
0x4007e7    push   r12
0x4007e9    push   rbx
0x4007ea    sub    rsp,0x258
0x4007f1    mov    rax,rsp
0x4007f4    mov    rbx,rax
7       int A;
8       cin >> A;
0x4007f7    lea    rax,[rbp-0x260]
0x4007fe    mov    rsi,rax
0x400801    mov    edi,0x601060
0x400806    call   0x4006e0 <std::istream::operator>>(int&)@plt>
9       int b[A];
0x40080b    mov    eax,DWORD PTR [rbp-0x260]
0x400811    cdqe
0x400813    sub    rax,0x1
0x400817    mov    QWORD PTR [rbp-0x270],rax
0x40081e    mov    rdx,rax
0x400821    add    rdx,0x1
0x400825    mov    r14,rdx
0x400828    mov    r15d,0x0
0x40082e    mov    rdx,rax
0x400831    add    rdx,0x1
0x400835    mov    r12,rdx
0x400838    mov    r13d,0x0
0x40083e    add    rax,0x1
0x400842    shl    rax,0x2
0x400846    lea    rdx,[rax+0x3]
0x40084a    mov    eax,0x10
0x40084f    sub    rax,0x1
0x400853    add    rax,rdx
0x400856    mov    ecx,0x10
0x40085b    mov    edx,0x0
0x400860    div    rcx
0x400863    imul   rax,rax,0x10
0x400867    sub    rsp,rax
0x40086a    mov    rax,rsp
0x40086d    add    rax,0x3
0x400871    shr    rax,0x2
0x400875    shl    rax,0x2
0x400879    mov    QWORD PTR [rbp-0x268],rax
10      int a[140];
11      for(int i = 0; i < A; i++)
0x400880    mov    DWORD PTR [rbp-0x27c],0x0
0x40088a    jmp    0x4008ac <main()+207>
0x4008a5    add    DWORD PTR [rbp-0x27c],0x1
0x4008ac    mov    eax,DWORD PTR [rbp-0x260]
0x4008b2    cmp    DWORD PTR [rbp-0x27c],eax
0x4008b8    jl     0x40088c <main()+175>
12          b[i] = i;
0x40088c    mov    rax,QWORD PTR [rbp-0x268]
0x400893    mov    edx,DWORD PTR [rbp-0x27c]
0x400899    movsxd rdx,edx
0x40089c    mov    ecx,DWORD PTR [rbp-0x27c]
0x4008a2    mov    DWORD PTR [rax+rdx*4],ecx
13      for(int i = 0; i < 140; i++)
0x4008ba    mov    DWORD PTR [rbp-0x278],0x0
0x4008c4    jmp    0x4008cd <main()+240>
0x4008c6    add    DWORD PTR [rbp-0x278],0x1
0x4008cd    cmp    DWORD PTR [rbp-0x278],0x8b
0x4008d7    jle    0x4008c6 <main()+233>
14          a[i];
15      for(int i = 0; i < A; i++)
0x4008d9    mov    DWORD PTR [rbp-0x274],0x0
0x4008e3    jmp    0x40090b <main()+302>
0x400904    add    DWORD PTR [rbp-0x274],0x1
0x40090b    mov    eax,DWORD PTR [rbp-0x260]
0x400911    cmp    DWORD PTR [rbp-0x274],eax
0x400917    jl     0x4008e5 <main()+264>
16          cout << b[i];
0x4008e5    mov    rax,QWORD PTR [rbp-0x268]
0x4008ec    mov    edx,DWORD PTR [rbp-0x274]
0x4008f2    movsxd rdx,edx
0x4008f5    mov    eax,DWORD PTR [rax+rdx*4]
0x4008f8    mov    esi,eax
0x4008fa    mov    edi,0x601180
0x4008ff    call   0x400680 <std::ostream::operator<<(int)@plt>
17      return 0;
0x400919    mov    eax,0x0
0x40091e    mov    rsp,rbx
18  }
0x400921    lea    rsp,[rbp-0x28]
0x400925    pop    rbx
0x400926    pop    r12
0x400928    pop    r13
0x40092a    pop    r14
0x40092c    pop    r15
0x40092e    pop    rbp
0x40092f    ret
0
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
12.09.2014, 00:53
Цитата Сообщение от Kerry_Jr Посмотреть сообщение
спокойно компилируется без каких-либо проблем.
Это называется VLA(variable length array), входят в стандарт С99, однако ни в одном из стандартов С++ не подтверждены. В gcc уже давно используется данная плюшка, но вот VS компиль до неё так и не дотянулся. Используйте динамические массивы заместо них.

Цитата Сообщение от ValeryS Посмотреть сообщение
а то что GNUс ведет себя не по стандарту это всем давно известно
ровно как и компиль vs

Добавлено через 1 минуту
Цитата Сообщение от FulcrumPlus Посмотреть сообщение
C++
1
2
3
4
for(int a=0;a<A;a++)
   {
delete BlockField_memory[A];
   }
C++
1
delete BlockField_memory[a];
0
5499 / 4894 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
12.09.2014, 01:17
Цитата Сообщение от MrGluck Посмотреть сообщение
delete BlockField_memory[a];
Тут разве память не под массивом освобождается?
0
835 / 643 / 101
Регистрация: 20.08.2013
Сообщений: 2,524
12.09.2014, 01:33
Цитата Сообщение от Kerry_Jr Посмотреть сообщение
спокойно компилируется без каких-либо проблем.
Интересно, а если напихать блоков, добавить переменных, что-нибудь похимичить и шмякнуть ещё goto, то тоже без проблем будет?)))

Добавлено через 1 минуту
Цитата Сообщение от FulcrumPlus Посмотреть сообщение
C++
1
delete BlockField_memory[A];
C++
1
delete[] BlockField_memory[A];
0
5499 / 4894 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
12.09.2014, 01:36
Цитата Сообщение от Qwertiy Посмотреть сообщение
C++
1
delete[] BlockField_memory[A];
Нет, выход за границу.
1
835 / 643 / 101
Регистрация: 20.08.2013
Сообщений: 2,524
12.09.2014, 01:48
Цитата Сообщение от alsav22 Посмотреть сообщение
Нет, выход за границу.
Блин.. Я невнимательный
Имел в виду, что надо скобочки delete'у поставить, а остальное скопипастил не проверяя. В общем, так:
C++
1
delete[] BlockField_memory[a];
0
5499 / 4894 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
12.09.2014, 02:01
Цитата Сообщение от Qwertiy Посмотреть сообщение
В общем, так:
4 пост.
1
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
12.09.2014, 10:37
Цитата Сообщение от alsav22 Посмотреть сообщение
Тут разве память не под массивом освобождается?
А это вторая явная ошибка. Я указал лишь на взятие неверного индекса т.к. это первое что бросилось в глаза.
Спасибо за уточнение.

Добавлено через 1 минуту
Да и не заметил, что у вас уже пример готовый есть.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
12.09.2014, 10:37
Помогаю со студенческими работами здесь

Почему это компилируется?
Компилятор не видит, что одному и тому же параметризованному типу присваивают разные типы? public static void main(String...

Выделение памяти под массив в классе. Почему не могу правильно выделить?
Все привет! не могу понять почему в классе не получается выделить память из стека для массива. Есть класс: Надо чтоб конструктор класса...

Конструктор класса по умолчанию: код компилируется, хотя по идее не должен
#include &lt;iostream&gt; class A {}; int main() { A i; A j(i); return 0;

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

Можно ли так выделить память в куче под указатель на массив?
Здравствуйте Можно ли выделить память в куче под указатель на массив например так:? int (*c)=(int (*)) new int; или нужно как...


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

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru