Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Ошибка при создании двумерного массива


Автор: Trurl 28.12.2007, 14:35
Подскажите, пожалуйста, в чём ошибка?

Код

 int * B = new int[N];

компилируется без проблем

Код

 int * B = new int[N][N];

возникает ошибка:
test.cpp(15) : error C2440: 'initializing' : cannot convert from 'int (*)[10]' to 'int *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

как можно тогда создать двумерный массив в динамической памяти?

С уважением.



Автор: Alexeis 28.12.2007, 14:48
Думаю примерно так 
Код

int **B = new int*[N]; // сначала массив указателей, потом отдельно память для каждого
for (int i = 0; i < N; i++){B[i] = new int[N];};

Автор: Trurl 28.12.2007, 19:11
Спасибо, не уверен, что мне это подойдёт.

Мне нужно сделать нечто следующее, но компилятор это не пропускает, хотя в одномерном случае всё ок.

Код

// test.cpp

#include <iostream>
#include <iomanip>

using namespace std;

# define N 10
void my_func(int * my_array);

int main()
{
 int * B = new int[N][N];

 my_func(B);

 delete [] B;
 
 return 0;
}

void my_func( int * my_array )
{
    for (int i = 0; i < N; i++)
    {
     for (int j = 0; j < N; j++)
     {
      my_array[i][j] = i + j + 1;
      cout << my_array[i][j] <<  "\t";
     }
     cout << endl;
    }
}



Автор: JackYF 28.12.2007, 19:15
Цитата(Trurl @  28.12.2007,  19:11 Найти цитируемый пост)
int * B

int** B, будь внимательней

Автор: Alexeis 28.12.2007, 20:22
Цитата(JackYF @  28.12.2007,  19:15 Найти цитируемый пост)
int** B, будь внимательней 

  Так и чего? Все равно разом нельзя так объявлять двумерный массив. Компилятор же не знает длину одной строки, как он сможет обратиться. Не тут только массив указателей.

Автор: archimed7592 28.12.2007, 21:56
Цитата(Trurl @  28.12.2007,  19:11 Найти цитируемый пост)
Мне нужно сделать нечто следующее
Цитата(Trurl @  28.12.2007,  19:11 Найти цитируемый пост)
# define N 10
Цитата(Trurl @  28.12.2007,  19:11 Найти цитируемый пост)
 int * B = new int[N][N];

Код

int (*B)[N] = new int[N][N];
// ...
delete [] B;


Добавлено через 1 минуту и 7 секунд
Цитата(Alexeis @  28.12.2007,  14:48 Найти цитируемый пост)
int **B
Цитата(Alexeis @  28.12.2007,  14:48 Найти цитируемый пост)
b[i] = new int[N];

С++ чуствителен к регистру smile.

Добавлено через 2 минуты и 17 секунд
Цитата(Trurl @  28.12.2007,  19:11 Найти цитируемый пост)
void my_func(int * my_array)

Код

void my_func(int (* my_array)[N])


Автор: Alexeis 29.12.2007, 00:13
  У варианта 
Цитата

int (*B)[N] = new int[N][N];
// ...
delete [] B;

  Только одно измерение динамическое.

Автор: archimed7592 29.12.2007, 10:39
Цитата(Alexeis @  29.12.2007,  00:13 Найти цитируемый пост)
 Только одно измерение динамическое. 

Я не зря наверное процитировал то, что N определено define'ом и представляет из себя константу smile.

Автор: Dov 29.12.2007, 11:24
Цитата(archimed7592 @  29.12.2007,  09:39 Найти цитируемый пост)
Я не зря наверное процитировал то, что N определено define'ом и представляет из себя константу 

В таком случае всё, что ты написал дальше, абсолютно лишнее, так как в этом случае динамическая квадратная матрица не нужна.  smile  

Автор: archimed7592 29.12.2007, 12:09
Цитата(Dov @  29.12.2007,  11:24 Найти цитируемый пост)
В таком случае всё, что ты написал дальше, абсолютно лишнее, так как в этом случае динамическая квадратная матрица не нужна.  smile  

На вашем месте я не был бы настолько категоричен.
1. N * N * sizeof(int) может оказаться в районе нескольких гигабайт.
2. Может оказаться необходимым продлить время жизни такого массива дальше чем конец текущего блока.

Если подумать, то, думаю, можно будет придумать ещё несколько примеров.

Автор: Dov 29.12.2007, 12:25
Цитата(archimed7592 @  29.12.2007,  11:09 Найти цитируемый пост)
1. N * N * sizeof(int) может оказаться в районе нескольких гигабайт.

 smile 
А почему не в районе нескольких сотен тысяч гигабайт?  smile 


archimed7592, ты же прекрасно понял о чём я сказал.  smile 

Или, всё-таки, не понял?  smile 

Автор: Fazil6 29.12.2007, 12:31
Цитата(Dov @  29.12.2007,  12:25 Найти цитируемый пост)
archimed7592, ты же прекрасно понял о чём я сказал.

ну и что? Я, например, тоже понял, но согласен с archimed7592. Динамический массив может требоваться не только исключительно незнанием его размера во время компилляции

Автор: archimed7592 29.12.2007, 12:32
Цитата(Dov @  29.12.2007,  12:25 Найти цитируемый пост)
А почему не в районе нескольких сотен тысяч гигабайт?  smile 

Может быть и в этом районе. Суть в том, что такие объёмы выделять на стеке не рационально.

Цитата(Dov @  29.12.2007,  12:25 Найти цитируемый пост)
Или, всё-таки, не понял?  smile  

Если честно, не особо понимаю.

Автор: MAKCim 29.12.2007, 12:37
Цитата(archimed7592 @  29.12.2007,  12:32 Найти цитируемый пост)
Суть в том, что такие объёмы выделять на стеке не рационально.

как раз таки рационально, в смысле в разы быстрее
другое дело, что таких больших стеков не бывает  smile

Добавлено через 4 минуты и 21 секунду
как вариант можно использовать
Код

void function() {
    static char array[N][N]
...
}

Автор: archimed7592 29.12.2007, 13:03
Цитата(MAKCim @  29.12.2007,  12:37 Найти цитируемый пост)
как раз таки рационально, в смысле в разы быстрее

Замечу, что я ни разу не упомянул о скорости smile.


Цитата(MAKCim @  29.12.2007,  12:37 Найти цитируемый пост)
другое дело, что таких больших стеков не бывает  smile

Об том и речь. Ну и время жизни для таких огромных объектов нет смысла делать автоматическим.


Цитата(MAKCim @  29.12.2007,  12:37 Найти цитируемый пост)
как вариант можно использовать

Это не совсем стек ;).

Автор: Alexeis 29.12.2007, 13:57
Цитата(MAKCim @  29.12.2007,  12:37 Найти цитируемый пост)
как вариант можно использовать
Код

void function() {
    static char array[N][N]
...
}




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

Цитата(MAKCim @  29.12.2007,  12:37 Найти цитируемый пост)
другое дело, что таких больших стеков не бывает

  В опциях проекта можно указать максимальный размер стека (под винду)

Цитата(archimed7592 @  29.12.2007,  13:03 Найти цитируемый пост)
Замечу, что я ни разу не упомянул о скорости smile.

  Опять же если смотреть под винду то скорость создания будет примерно такой же, как и в стеке, потому что винда не дурная чтобы гиг стека без нужды с оперативе держать. 

Хотя пожалуй archimed7592 прав. Просто тут есть путаница, под динамическим массивом можно понимать массив динамической длинны или выделенный в куче smile это немного разное.

Автор: archimed7592 29.12.2007, 14:10
Цитата(Alexeis @  29.12.2007,  13:57 Найти цитируемый пост)
Насколько я знаю такой массив создаться точно также как обычная глобальная переменная, то только ее имя будет локализовано, потому для гигабайта не катит.

Не совсем так. Есть три вида storage duration: automatic, dynamic и static. В общем случае для каждого из видов предусмотрена отдельная "область" памяти. Для автоматических объектов это стек, для динамических - куча, а для статических - точно сказать не могу, но, AFAICS это просто область в сегменте данных, выделяемая в момент старта программы.

Цитата(Alexeis @  29.12.2007,  13:57 Найти цитируемый пост)
В опциях проекта можно указать максимальный размер стека (под винду)

Сколько раз указывал - винда разом не выделяла огромный объём под стек smile.

Автор: Alexeis 29.12.2007, 14:20
Цитата(archimed7592 @  29.12.2007,  14:10 Найти цитируемый пост)
Сколько раз указывал - винда разом не выделяла огромный объём под стек smile. 

  В том то и дело если она начнет его наращивать, то быстрее не будет.

Автор: MAKCim 29.12.2007, 18:41
Цитата(archimed7592 @  29.12.2007,  13:03 Найти цитируемый пост)
Это не совсем стек ;). 

Замечу, что я ни разу не упомянул о стеке  smile

Добавлено через 2 минуты и 5 секунд
Цитата(Alexeis @  29.12.2007,  13:57 Найти цитируемый пост)
потому для гигабайта не катит.

очень даже катит
причем это будет самый быстрый способ выделения памяти
+ данные будут располагаться в BSS секции, что не увеличивает размер выходного файла

Автор: Alexeis 29.12.2007, 18:46
Цитата(MAKCim @  29.12.2007,  18:41 Найти цитируемый пост)
+ данные будут располагаться в BSS секции, что не увеличивает размер выходного файла

  Че это за секция такая? Т.е. в экзешнике не резерируется место под статик переменные? Они что создаются на этапе инициализации?

Автор: bsa 29.12.2007, 19:03
Alexeis, думаю, только статические константы встроенных типов могут располагаться в сегменте кода.

Автор: MAKCim 29.12.2007, 19:05
Цитата(Alexeis @  29.12.2007,  18:46 Найти цитируемый пост)
Че это за секция такая? Т.е. в экзешнике не резерируется место под статик переменные? Они что создаются на этапе инициализации?

неинициализированные глобальные (статические и не статические) и локальные статические данные располагаются в BSS секции
я не знаком с форматом файлов PE
однако могу сказать про реализацию BSS в формате ELF
там есть такое понятие как таблица дескрипторов програмных сегментов
каждый програмный сегмент имеет определенный тип
особое положение занимают сегменты с типом PT_LOAD, т. е загружаемые програмные сегменты
по ним осуществляется отображение образа программы (библиотеки) на адресное пространство процесса
каждый дескриптор имеет два очень важных компонента: FileSiz и MemSiz
разность значений MemSiz - FileSiz дает размер BSS секции образа программы (библиотеки)
т. е, например, если где-то в коде определен неинициализированный массив размером в 1ГБ, то
MemSiz = FileSiz + 1024 * 1024 * 1024
при этом значение FileSiz равно общему размеру всех инициализированных данных
(явно определенных в коде или неявно создаваемых компилятором / компоновщиком)
при динамической компоновке (загрузчиком ядра или пользовательского уровня (ld.so))
отображается FileSiz-часть образа программы (библиотеки) и выделяется MemSiz - FileSiz байт для BSS

Автор: archimed7592 29.12.2007, 19:20
Цитата(Alexeis @  29.12.2007,  18:46 Найти цитируемый пост)
Т.е. в экзешнике не резерируется место под статик переменные?

Да, вообще говоря, на такие переменные и так не выделяется...

Цитата(MAKCim @  29.12.2007,  18:41 Найти цитируемый пост)
Замечу, что я ни разу не упомянул о стеке  smile

 smile 


Цитата(MAKCim @  29.12.2007,  18:41 Найти цитируемый пост)
очень даже катит
причем это будет самый быстрый способ выделения памяти

Ну, тебе виднее smile.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)