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

С++ VLA и прочее... - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.89
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
30.11.2012, 00:17     С++ VLA и прочее... #1
 Комментарий модератора 
Перенесено из Порекомендуйте компилятор


Dev-C++ меня удивляет. Вот такой код компилирует без ошибок и предупреждений:
C++
1
2
3
4
5
6
7
int main()
{
    int m;
    int arr[m];
    
    return 0;
}
А такой и выполняет:
C++
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
using namespace std;
 
int main()
{
    int m;
    cin >> m;
    int arr[m];
    
    return 0;
}
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,270
30.11.2012, 00:40     С++ VLA и прочее... #2
Второй код считаю нормальным.
Первый говнокод конечно, но при чём тут IDE? За вывод предупреждений она не ответственна, а то щас наговоришь тут. За предупреждения ответственен компилятор (там стоит gcc). Открываешь в DEV параметры компилятора и пишешь (это нужно уметь делать безусловно) -Wall в опциях и будет круто; в обоих случаях выведутся предупреждения.

В книжке Артура Гриффитса подробно всё описано.
Dima_c8
 Аватар для Dima_c8
4 / 4 / 0
Регистрация: 17.12.2011
Сообщений: 148
30.11.2012, 00:43     С++ VLA и прочее... #3
кстати вроде по теме а как там в деве запустить функцию InitCommonControls а то не работает
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
30.11.2012, 01:03  [ТС]     С++ VLA и прочее... #4
Цитата Сообщение от kravam Посмотреть сообщение
Второй код считаю нормальным.
Размер статического массива должен быть известен на момент компиляции. Иначе, как под него память выделять?

Цитата Сообщение от kravam Посмотреть сообщение
Открываешь в DEV параметры компилятора и пишешь (это нужно уметь делать безусловно)
Особенно начинающему... Научи, где что писать.

Добавлено через 8 минут
Цитата Сообщение от kravam Посмотреть сообщение
Первый говнокод конечно, но при чём тут IDE? За вывод предупреждений она не ответственна, а то щас наговоришь тут. За предупреждения ответственен компилятор (там стоит gcc).
Начинающий не будет возиться с подключением другого компилятора к IDE. Для него это всё - IDE.
MrGluck
Ворчун
Эксперт С++
 Аватар для MrGluck
4920 / 2663 / 243
Регистрация: 29.11.2010
Сообщений: 7,405
30.11.2012, 01:23     С++ VLA и прочее... #5
Цитата Сообщение от alsav22 Посмотреть сообщение
Размер статического массива должен быть известен на момент компиляции. Иначе, как под него память выделять?
Оно преобразует переменную и создает статический массив на момент обращения. А void main по-умолчанию и include "stdafx" какой-то куда лучше. А ведь, пропустив автоматом пункт, где надо убрать галочку (а новичок побоится вмешиваться в дефолтные настройки), абсолютно нормальный код не скомпилится. Не говоря уж о том, что студия пытается везде пропихнуть свои стандарты, пугая списком варнингов типа юзай непереносимое printf_s заместо абсолютно нормального printf. Да, можно довести студию до ума, но это уже разбираясь в настройках. Ну и второй код с VLA (variable length array) не считаю слишком критичным. Уж кто бы говорил о стандартах, так это точно не продукты от Microsoft.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
30.11.2012, 01:35  [ТС]     С++ VLA и прочее... #6
Цитата Сообщение от MrGluck Посмотреть сообщение
А ведь, пропустив автоматом пункт, где надо убрать галочку (а новичок побоится вмешиваться в дефолтные настройки), абсолютно нормальный код не скомпилится
Поэтому я всем советую создавать пустой проект, там галочки не нужно ставить.
Цитата Сообщение от MrGluck Посмотреть сообщение
Не говоря уж о том, что студия пытается везде пропихнуть свои стандарты
С этим согласен.
Цитата Сообщение от MrGluck Посмотреть сообщение
Уж кто бы говорил о стандартах, так это точно не продукты от Microsoft.
С этим тоже согласен, но насчёт размерности массива, причёт здесь Microsoft? Об этом разговоры здесь были и , если я не прав, пусть поправят, но я так понял, что именно по стандарту размер статического массива должен быть величиной константной, а значит известной на момент компиляции.
activnaya
 Аватар для activnaya
255 / 45 / 2
Регистрация: 24.11.2012
Сообщений: 466
30.11.2012, 01:39     С++ VLA и прочее... #7
alsav22, а что тут собственно не устраивает? память, отведенная под m уже содержит значения, то что кододел ее не инициализировал своим значением, это его проблемы.
C++
1
2
3
4
5
6
7
int main()
{
    int m;
    int arr[m];
    
    return 0;
}
Как заметил MrGluck, VLA даже в Сишке есть. Начиная с Си99 это очень корректный код.
C
1
2
3
4
5
void f(size_t n)
{
    int array[n];
    ...
}
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
30.11.2012, 02:52  [ТС]     С++ VLA и прочее... #8
Вопрос не о том, что кого устраивает или не устраивает. Вопрос о том, как правильно. Как тогда это понимать? http://www.cplusplus.com/doc/tutorial/arrays/
NOTE: The elements field within brackets [] which represents the number of elements the array is going to hold, must be a constant value, since arrays are blocks of non-dynamic memory whose size must be determined before execution. In order to create arrays with a variable length dynamic memory is needed, which is explained later in these tutorials.
Добавлено через 15 минут
Вот эти объяснения, как понимать? Массивы. Статические и динамические
MrGluck
Ворчун
Эксперт С++
 Аватар для MrGluck
4920 / 2663 / 243
Регистрация: 29.11.2010
Сообщений: 7,405
30.11.2012, 03:02     С++ VLA и прочее... #9
alsav22, http://www.open-std.org/JTC1/SC22/WG...docs/n1336.pdf
However, an object declared with the static storageclass specifier can have a VM type (that is, a pointer to a VLA type). Finally, all identifiers declared with a
VM type have to be ordinary identifiers and cannot, therefore, be members of structures or unions.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
extern int n;
int A[n]; // invalid file scope VLA
extern int (*p2)[n]; // invalid file scope VM
int B[100]; // invalid file scope but not VM
void fvla(int m, int C[m][m]); // valid: VLA with prototype scope
void fvla(int m, int C[m][m]) // valid: adjusted to auto pointer to VLA
{
typedef int VLA[m][m]; // valid: block scope typedef VLA
struct tag {
int (*y)[n]; // invalid: y not ordinary identifier
int z[n]; // invalid: z not ordinary identifier
};
int D[m]; // valid: auto VLA
static int E[m]; // invalid: static block scope VLA
extern int F[m]; // invalid: F has linkage and is VLA
int (*s)[m]; // valid: auto pointer to VLA
extern int (*r)[m]; // invalid: r has linkage and points to VLA
static int (*q)[m] = &B; // valid: q is a static block pointer to VLA
}
Добавлено через 5 минут
Кстати, на С++, по-моему, даже в С++11 это не по стандарту. Но это тот же сценарий, что и long long int.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,270
30.11.2012, 12:11     С++ VLA и прочее... #10
Цитата Сообщение от alsav22 Посмотреть сообщение
Размер статического массива должен быть известен на момент компиляции. Иначе, как под него память выделять?
А как вообще память под массивы выделяется? Мне кажется функция начинает работать и только тогда выделяется память под массив в стеке. Скорее всего просто указатель на верхушку стека просто-напросто уменьшается на нужное количество байт (в данном случае на m байт). Всё память выделена. ВО ВРЕМЯ РАБОТЫ ФУНКЦИИ main. Проверить так это ли нет- в отладчике сложно. Но можно в том же отладчике посмотреть, откуда функция берёт элементы массива (хотя тут m известно на начало работы, но это не главное, главное, ГДЕ ВЫДЕЛЯЕТСЯ ПАМЯТЬ ПОД МАССИВ)

C++
1
2
3
4
5
6
7
8
#include <stdio.h>
int main()
{
    int m= 0X100;
    int arr[m];
    printf ("%d\n", arr [0]); 
    return 0;
}
А выделяется она в стеке; и она может выделиться так, а может выделиться эдак. Отсюда вывод: выделяется она во время работы функции. И следующий вывод: поэтому ничто (кроме больших размеров) не мешает тому, чтобы размер массива (величина стека, выделенного под него) был определён во время работы функции.

Цитата Сообщение от alsav22 Посмотреть сообщение
Особенно начинающему... Научи, где что писать.
Я уже научил. Уже можно по тому, что я сказал, найти настройки компилятора и место, где прописывать опции, DEV компактна довольна. Там негде особо блудить.
И ещё научу, надо будет. Скажем так: и там и там начинающий сталкивается с определёнными трудностями. Так по мне пусть он лучше некорректным кодом пропишет память (а рано или поздно он всё равно это сделает) и научится, как этого избегать (твой первый код), чем увидит чудо-юдо-рыбу-кит например: strcpy_s, которая ни в одном учебнике по C не упоминается.

Цитата Сообщение от alsav22 Посмотреть сообщение
Начинающий не будет возиться с подключением другого компилятора к IDE. Для него это всё - IDE.
Ну и пусть работает с тем, что дают, а подключает ПОТОМ, когда станет неначинающим.
XRuZzz
Антикодер
577 / 478 / 23
Регистрация: 15.09.2012
Сообщений: 2,429
30.11.2012, 12:21     С++ VLA и прочее... #11
+1 голос за gcc в линухе, на Gentoo библиотеки ставятся автоматически системой портов, что уменьшает количество проблем при их подключении.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
30.11.2012, 20:15  [ТС]     С++ VLA и прочее... #12
Цитата Сообщение от kravam Посмотреть сообщение
Мне кажется функция начинает работать и только тогда выделяется память под массив в стеке
Неправильно кажется. Память в стеке, под переменные, выделяется до начала работы main(). В этом всё и дело. Как выделить память, если размер её неизвестен?
Миниатюры
С++ VLA и прочее...  
activnaya
 Аватар для activnaya
255 / 45 / 2
Регистрация: 24.11.2012
Сообщений: 466
30.11.2012, 20:19     С++ VLA и прочее... #13
Цитата Сообщение от alsav22 Посмотреть сообщение
Память в стеке, под переменные, выделяется до начала работы main().
да ну, а stack overflow придумали троли
Герц
523 / 340 / 4
Регистрация: 05.11.2010
Сообщений: 1,077
Записей в блоге: 1
30.11.2012, 20:21     С++ VLA и прочее... #14
Второй код считаю нормальным.
Ты может и считаешь, а стандарт C++ - нет.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
30.11.2012, 21:23  [ТС]     С++ VLA и прочее... #15
Цитата Сообщение от MrGluck Посмотреть сообщение
owever, an object declared with the static storageclass specifier can have a VM type (that is, a pointer to a VLA type). Finally, all identifiers declared with a
VM type have to be ordinary identifiers and cannot, therefore, be members of structures or unions.Код C++

extern int n;
int A[n]; // invalid file scope VLA
extern int (*p2)[n]; // invalid file scope VM
int B[100]; // invalid file scope but not VM
void fvla(int m, int C[m][m]); // valid: VLA with prototype scope
void fvla(int m, int C[m][m]) // valid: adjusted to auto pointer to VLA
{
typedef int VLA[m][m]; // valid: block scope typedef VLA
struct tag {
int (*y)[n]; // invalid: y not ordinary identifier
int z[n]; // invalid: z not ordinary identifier
};
int D[m]; // valid: auto VLA
static int E[m]; // invalid: static block scope VLA
extern int F[m]; // invalid: F has linkage and is VLA
int (*s)[m]; // valid: auto pointer to VLA
extern int (*r)[m]; // invalid: r has linkage and points to VLA
static int (*q)[m] = &B; // valid: q is a static block pointer to VLA
}
MrGluck, не могли бы вы хоть как-то прокоментировать эту цитату. Для меня, как начинающего, сложно понять о чём тут речь.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,270
30.11.2012, 21:36     С++ VLA и прочее... #16
Пришла пора расставить всё на свои места.

Цитата Сообщение от alsav22 Посмотреть сообщение
Неправильно кажется. Память в стеке, под переменные, выделяется до начала работы main(). В этом всё и дело. Как выделить память, если размер её неизвестен?
посмотрел твою цитату; кто такое пишет ему руки надо оторвать, цитату можно понимать двояко (а нужно чтобы она понималась ОДНОЗНАЧНО).

Давай всё-таки разделим мухи отдельно, котлеты отдельно. Есть понятие "выделение стека", а есть понятие "выделение памяти в стеке."На самом деле по твоей цитате речь идёт первом, то есть программе выделяется кусок памяти и говорится: "это стек, запихивай туда свои данные". Иначе и быть не может. Но можно предположить и второй вариант (мою версию выделения памяти)- так уж она скользко написана.

Цитата Сообщение от alsav22 Посмотреть сообщение
Как выделить память, если размер её неизвестен?
Это если предполагать, что память под локальные переменные выделяется до начала main (твои предположения);а если она выделяется в процессе main, то всё становится на свои места.

Поэтому смотрим своими глазами где что и как выделяется, поехали:


Проверяем, вот код:
C++
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
using namespace std;
 
int main()
{
    int m= 0X5555666;
    printf ("%x\n", m);
    getchar ();
    return 0;
}
Так ты говоришь, память под переменную m выделится до начала main? запускаем прогу в отладчике, вот на нулевом рисунке ясно показана программа В НАЧАЛЕ РАБОТЫ, в правом нижнем углу СТЕК и я стрелками показал, что в стеке нет НИЧЕГО ПОХОЖЕГО на 0X5555666

Но, может быть, значения нет, а ячейка памяти выделена? Ни фига подобного, трассируем до момента, когда значение 0x55556666 будет занесено в стек, вот эта инструкция (ris_1.), я на неё показываю стрелкой, кроме того мы видим, что стек с начала работы охренительно увеличился и только ПОСЛЕ ВЫПОЛНЕНИЯ ЭТОЙ ИНСТРУКЦИИ в стек будет положено значение 0X5555666; куда именно я указал пятью восклицательными знаками.

Ну и наконец последняя картинка (ris_2) это мы видим что по адресу в стеке 0X22ff4C РЕАЛЬНО положилось значение 0X5555666 и случилось это непосредственно перед вызовом printf, а далеко не перед началом работы main; ну то есть вышло так: сперва выделена ячейка памяти, через некоторое время (не сразу) туда занесено значение 0X5555666
Миниатюры
С++ VLA и прочее...   С++ VLA и прочее...   С++ VLA и прочее...  

alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
30.11.2012, 22:54  [ТС]     С++ VLA и прочее... #17
Цитата Сообщение от kravam Посмотреть сообщение
Так ты говоришь, память под переменную m выделится до начала main?
Это не только я говорю, и не один я говорю. Многие говорят. Не раз, и не два встречал. Например, здесь: Размер статического массива
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,270
30.11.2012, 23:27     С++ VLA и прочее... #18
Цитата Сообщение от ~OhMyGodSoLong~ Посмотреть сообщение
Место под все локальные переменные выделяется перед выполнением кода функции. Сколько этого места понадобится
А чё сказать? Я показал на пальцах, что место под локальную переменную m выделилось В ПРОЦЕССЕ выполнения кода, а не перед. Но чел убеждён что "перед". Ну пусть так и будет, мне-то что.

Цитата Сообщение от ~OhMyGodSoLong~ Посмотреть сообщение
когда его инициализировать, решает компилятор
с этим согласен

Добавлено через 9 минут
НЕ поленился щас вот такой код глянуть:
C++
1
2
3
4
5
6
#include <stdio.h>
int main()
{
    char arr[]= "rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr";
    return 0;
}
Да. Всё так и есть. В начале main стек мал и пуст. А где-то в середине программы стек УВЕЛИЧИЛСЯ и перегоняет туда эту строку. (Ставил нардварный бряк на этой строке в секции данных и смотрел, когда к ней будет обращение); могу скриншоты скинуть.
Герц
01.12.2012, 00:04
  #19

Не по теме:

C++
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
using namespace std;
 
int main()
{
    int m= 0X5555666;
    printf ("%x\n", m);
    getchar ();
    return 0;
}
Большой знаток C++ пришел :-D
using namespace std; и ни одного C++ заголовка.

MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.12.2012, 00:05     С++ VLA и прочее...
Еще ссылки по теме:

C++ Размер примитивных типов, выравнивание и прочее
Инкремент, декремент и прочее. A+++ - что означают это три плюса C++
C++ Рекурентная формула и прочее

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

Или воспользуйтесь поиском по форуму:
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
01.12.2012, 00:05     С++ VLA и прочее... #20
А ничего, что в стеке хранятся не только записи активаций функций, а и вагон с тележкой другой лабуды вроде записей активаций системных вызовов и SEH-фреймов, и кто-то должен за ними убирать, чтобы user-функции не напоролись на то, что им видеть не положено?
Yandex
Объявления
01.12.2012, 00:05     С++ VLA и прочее...
Ответ Создать тему
Опции темы

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