Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.66/375: Рейтинг темы: голосов - 375, средняя оценка - 4.66
Технофашист
229 / 217 / 11
Регистрация: 11.03.2009
Сообщений: 887

Динамический массив указателей

04.09.2010, 08:34. Показов 72028. Ответов 28
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Чегото не пойму такое вообще возможно?
Странно, что при объявлении можно не указывать размерность: int *a[];
Но как потом память выделять не известно.

Добавлено через 2 минуты
p.s. прошу не путать с указателем на массив.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
04.09.2010, 08:34
Ответы с готовыми решениями:

Динамический массив указателей
Есть класс "блока" - MapBuilderClass::BlockClass. Надо создать массив из MapBuilderClass::BlockClass* (из указателей на "блок"),...

Динамический массив указателей
есть вот такой массив. void* pppribarray = { NULL, NULL, NULL, NULL }; каждый его элемент это указатель на разные пользовательские типы...

Динамический массив указателей
Нужен массив указателей на тип родительского класса Game, как его правильно оформить? То что я написал выдает ошибку. #include...

28
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
28.12.2016, 04:22
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от darkAngel Посмотреть сообщение
((int*)ppv[i])[j]
Да в MSVС тоже работает.

Цитата Сообщение от darkAngel Посмотреть сообщение
error: 'void*' is not a pointer-to-object type
По-моему все предельно понятно.
Ничего не понятно. Указатель Void не является типом - "указатель на объект"?.. Что то бредово как то, а чем же тогда он является?..

Вы сами то как думаете?..
Цитата Сообщение от darkAngel Посмотреть сообщение
Во 2 варианте сперва просиходит доступ к элементам типа void**: после первых квадратных скобок мы получаем указатель на void*, а после вторых - void. И после этого уже пытаемся привести тип void к типу int**.
Вот опять.. если опустить последнюю фразу(заменить int** на int).. то чисто теоретически у нас есть уже адрес указателя после второй скобки. Так почему нельзя кастануть на (int) уже после получения адреса?..
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13229 / 6861 / 1827
Регистрация: 18.10.2014
Сообщений: 17,391
28.12.2016, 05:01
Цитата Сообщение от Izual Посмотреть сообщение
Ничего не понятно. Указатель Void не является типом - "указатель на объект"?.. Что то бредово как то
Все правильно, ничего бредового. Объектов типа void нет и быть не может, ибо void - неполный тип, который не может быть сделан полным.

Цитата Сообщение от Izual Посмотреть сообщение
а чем же тогда он является?
А является он просто указателем на тип void - ни больше, ни меньше.

------

Доступ к массиву с элементами типа void * через указатель типа int ** является "грязным хаком" - переинтерпретацией памяти, нарушением strict aliasing и, как следствие, неопределенным поведением.

C++
1
2
3
4
5
6
7
8
9
10
int i0[5] = { 1, 2, 3, 4, 5 };
int i1[5] = { 6, 7, 8, 9, 10 };
int i2[5] = { 11, 12, 13, 14, 15 };
 
void *va[] = { i0, i1, i2 };
 
int **ia = (int **) va; // <- Это - reinterpret_cast
int *p = ia[1]; // <- Неопределенное поведение, дальше можно не смотреть
 
std::cout << p[2] << std::endl;
Доступ к тому же массиву через оригинальный указатель типа void ** является совершенно законным, как является законным и преобразование прочитанного void * к типу int * и дальнейшая работа через этот int * указатель (подразумевая, что он указывает в правильное место)

C++
1
2
3
4
5
6
7
8
9
int i0[5] = { 1, 2, 3, 4, 5 };
int i1[5] = { 6, 7, 8, 9, 10 };
int i2[5] = { 11, 12, 13, 14, 15 };
 
void *va[] = { i0, i1, i2 };
 
int *p = (int * ) va[1]; // <- Это - static_cast
 
std::cout << p[2] << std::endl; // Печатаем 8
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13229 / 6861 / 1827
Регистрация: 18.10.2014
Сообщений: 17,391
28.12.2016, 05:56
Цитата Сообщение от Izual Посмотреть сообщение
Ничего не понятно. Указатель Void не является типом - "указатель на объект"?.. Что то бредово как то
Все правильно, ничего бредового. Объектов типа void нет и быть не может, ибо void - неполный тип, который не может быть сделан полным.

Цитата Сообщение от Izual Посмотреть сообщение
а чем же тогда он является?
А является он просто указателем на тип void - ни больше, ни меньше.

------

Доступ к массиву с элементами типа void * через указатель типа int ** является "грязным хаком" - переинтерпретацией памяти, нарушением strict aliasing и, как следствие, неопределенным поведением

C++
1
2
3
4
5
6
7
8
9
10
int i0[5] = { 1, 2, 3, 4, 5 };
int i1[5] = { 6, 7, 8, 9, 10 };
int i2[5] = { 11, 12, 13, 14, 15 };
 
void *va[] = { i0, i1, i2 };
 
int **ia = (int **) va; // <- Это - reinterpret_cast
int *p = ia[1]; // <- Неопределенное поведение, дальше можно не смотреть
 
std::cout << p[2] << std::endl;
Доступ к тому же массиву через оригинальный указатель типа void ** является совершенно законным, как является законным и преобразование прочитанного void * к типу int * и дальнейшая работа через этот int * указатель (подразумевая, что он указывает в правильное место)

C++
1
2
3
4
5
6
7
8
9
int i0[5] = { 1, 2, 3, 4, 5 };
int i1[5] = { 6, 7, 8, 9, 10 };
int i2[5] = { 11, 12, 13, 14, 15 };
 
void *va[] = { i0, i1, i2 };
 
int *p = (int *) va[1]; // <- Это - static_cast. Теперь `p` указывает на начало `i1`
 
std::cout << p[2] << std::endl; // Печатаем 8
Добавлено через 42 минуты

Не по теме:

Ну вот, глюки сервера приводят к дупликации сообщений...

0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
28.12.2016, 12:18
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Объектов типа void нет и быть не может
Мне не нужен объект типа void, мне нужен указатель на ячейку памяти, а уже дальше должен идти каст для того чтоб получить данные конкретного типа. Я вроде это уже писал.
Спс конешно, но объяснение не дошло.. видимо потому что оно не объясняет нифига) Покрайней мере не со стороны здравой логики, я конешно тоже понимаю что нужно знать ещё и инструмент с которым работаеш, но именно поэтому и вопрос возник, что инструмент выдаёт ошибку. (ну и тут либо я чего то неправильно делаю, либо инструмент собирали в соседнем подвале)
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13229 / 6861 / 1827
Регистрация: 18.10.2014
Сообщений: 17,391
28.12.2016, 12:54
Цитата Сообщение от Izual Посмотреть сообщение
Мне не нужен объект типа void, мне нужен указатель на ячейку памяти, а уже дальше должен идти каст для того чтоб получить данные конкретного типа.
Это прекрасно. Имено для этого тип void * и предназначен. Однако это не указатель на "ячейку" в памяти. Это указатель на точку в памяти. Чтобы из него получить указатель на некую "ячейку", вам тоже придется применить каст и привести указатель к типу "указатель на ячейку" (что бы вы ни понимали под "ячейкой"). Указателем на минимальную ячейку в языках С и С++ является указатель типа [signed/unsigned] char *, но не void *. void * указывает на точку. Это просто адрес.

И у точки нет размера. Поэтому если где-либо в коде вы вдруг попытаетесь использовать указатель типа void * так, что компилятору понадобиться знать размер указуемого объекта, то ваш код будет некорректным. Диагностическое сообщение от компилятора может быть сформулировано по-разному, но суть его всегда одна и та же: так как void не является полным типом, его размер комилятору неизвестен и любые операции, требующие знания этого размера, являются ошибочными.

В частности, применение оператора [] к указателю типа void * является некорректным. Оператор [] опирается на адресную арифметику. А адресная арифметика требует знания размера указуемого объекта. Так как у void нет размера, адресная арифметика к указателю типа void * не применима.

И т.д.
1
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
29.12.2016, 04:02
Получилось что то типа этого:
C++
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
int UsFunction4()
{
    int fRes=0;
    int *pi=NULL;
    char *pc=NULL, *mc[]={"first","second","third"};
    unsigned short *pus=NULL, mus[3]={6};
    float *pf=NULL, mf[3]={1.11};
    double *pd=NULL, md[3]={3.14,7.66,1.23};
    char *fBufx[]={"(char*)","(unsigned short*)","(float*)","(double*)"};
    int **ppm;
    //unsigned long long MXsize = 10;
    cout << "0. **ppm adress: " << &ppm << endl;
    cout << "1. (PTR[])Char address: " << &pc << endl;
    cout << "2. Char Massive address: " << &mc[0] << ", and Data(0): " << mc[0] << endl;
    if(pc!=NULL){ cout << "(PTR)Char != NULL <ER-1>" << endl; fRes=-1;}
    else{ pc = *mc;
        if(pc==NULL){ cout << "(PTR)Char == NULL <ER-2>" << endl; fRes=-2;}
        else{ cout << "New ptr adress:" << &pc << " and Data: " << pc << " and *pc: " << *pc << endl; }
    }
    cout << "3. Unsigned_Short Massive address: " << &mus[0] << ", and Data(0): " << mus[0] << endl;
    if(pus!=NULL){ cout << "(PTR)US != NULL <ER-3>" << endl; fRes=-3;}
    else{ pus = mus;
        if(pus==NULL){ cout << "(PTR)US == NULL <ER-4>" << endl; fRes=-4;}
        else{ cout << "New ptr adress:" << &pus << " and Data: " << *pus << endl; }
    }
    cout << "4. Float Massive address: " << &mf[0] << ", and Data(0): " << mf[0] << endl;
    if(pf!=NULL){ cout << "(PTR)Float != NULL <ER-5>" << endl; fRes=-5;}
    else{ pf = mf;
        if(pf==NULL){ cout << "(PTR)Float == NULL <ER-6>" << endl; fRes=-6;}
        //else{ printf("New ptr adress: %ld; and Data: %f; and *pc: %ld\n",&pf,pf,*pf);}
        else{ cout << "New ptr adress:" << &pf << " and Data: " << *pf << endl; }
    }
    cout << "5. Double Massive address: " << &md[0] << ", and Data(0): " << md[0] << endl;
    if(pd!=NULL){ cout << "(PTR)Double != NULL <ER-7>" << endl; fRes=-7;}
    else{ pd = md;
        if(pd==NULL){ cout << "(PTR)Double == NULL <ER-8>" << endl; fRes=-8;}
        else{ cout << "New ptr adress:" << &pd << " and Data: " << *pd << endl; }
    }
    ppm = new(nothrow) int* [MXsize]; // создали 10 указателей на указатели
    if(ppm == NULL)
        return -3;
    for(int i=0;i<MXsize;i++){ppm[i]=NULL;}
    for(int i=0;i<MXsize;i++){cout << "**ppm[" << i << "] adress: " << &ppm[i];
    if(ppm[i]==NULL) cout << ". No data" << endl;
    else cout << ". data: " << ppm[i] << endl;}
    ppm[0]=(int*)mc;
    ppm[1]=(int*)mus;
    ppm[2]=(int*)mf;
    ppm[3]=(int*)md;
    if(ppm[0]!=NULL){ cout << "pChar-M[0] adress: " << &ppm[0] << endl;
    for(int i=0;i<3;i++){cout << fBufx[0] << "Ppm[" << i << "] Data = " << (char*)ppm[0][i] << " DataAdr: " << &ppm[0][i] << endl;}
    cout << "PTRC Data = " << *(char**)ppm[0] << " DataAdr: " << &ppm[0][0] << endl;
    //cout << "PTRC Data = " << (char*)ppm[0][0] << " DataAdr: " << &ppm[0][0] << endl;
    cout << "pUS-M[1] adress: " << &ppm[1] << endl;
    for(int i=0;i<3;i++){cout << fBufx[1] << "Ppm[" << i << "] Data = " << ((unsigned short*)ppm[1])[i] << " DataAdr: " << &ppm[1][i] << endl;}
    cout << "pFloat-M[2] adress: " << &ppm[2] << endl;
    for(int i=0;i<3;i++){cout << fBufx[2] << "Ppm[" << i << "] Data = " << ((float*) ppm[2])[i] << " DataAdr: " << &ppm[2][i] << endl;}
    cout << "pDouble-M[3] adress: " << &ppm[3] << endl;
    for(int i=0;i<3;i++){cout << fBufx[3] << "Ppm[" << i << "] Data = " << ((double*)ppm[3])[i] << " DataAdr: " << &ppm[3][i] << endl;}}
    else cout << "ppm[0] adress: " << &ppm[0] << " and it is NULL" << endl;
    delete [] ppm;
    return fRes;
}
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13229 / 6861 / 1827
Регистрация: 18.10.2014
Сообщений: 17,391
29.12.2016, 07:33
Цитата Сообщение от Izual Посмотреть сообщение
Получилось что то типа этого:
Какие-то непонятно зачем сделанные и что означающие манипуляции...

Цитата Сообщение от Izual Посмотреть сообщение
C++
1
cout << "0. **ppm adress: " << &ppm << endl;
Печатается &ppm, а в сообщении почему-то написано "**ppm adress"...

Цитата Сообщение от Izual Посмотреть сообщение
C++
1
cout << "1. (PTR[])Char address: " << &pc << endl;
Что такое "(PTR[])" вообще? Печатается просто адрес локальной переменной типа char *.

Цитата Сообщение от Izual Посмотреть сообщение
C++
1
cout << "New ptr adress:" << &pc
Почему это называется "New ptr adress" - не ясно. Величина &pc внутри функции всегда была и будет одной и той же. Ее невозможно поменять.

Эта же страннная печать "New ptr adress" повторяется много раз ниже.

Цитата Сообщение от Izual Посмотреть сообщение
C++
1
ppm = new(nothrow) int* [MXsize]; // создали 10 указателей на указатели
Ым... Нет, здесь создается 10 указателей на int. Указатель на указатель тут только один - ppm.

Цитата Сообщение от Izual Посмотреть сообщение
C++
1
for(int i=0;i<MXsize;i++){cout << "**ppm[" << i << "] adress: " << &ppm[i];
Опять странное сообщение **ppm[i]: когда на самом деле печатается &ppm[i].

Цитата Сообщение от Izual Посмотреть сообщение
C++
1
2
3
4
ppm[0]=(int*)mc;
ppm[1]=(int*)mus;
ppm[2]=(int*)mf;
ppm[3]=(int*)md;
В дело пошел reinterpret_cast. Запахло жареным...

Цитата Сообщение от Izual Посмотреть сообщение
C++
1
for(int i=0;i<3;i++){cout << fBufx[0] << "Ppm[" << i << "] Data = " << (char*)ppm[0][i] << " DataAdr: " << &ppm[0][i] << endl;}
Чтение ppm[0][i] - неопределенное поведение. Легальность адресной арифметики в ppm[0][i] сомнительна...

Цитата Сообщение от Izual Посмотреть сообщение
C++
1
cout << "PTRC Data = " << *(char**)ppm[0] << " DataAdr: " << &ppm[0][0] << endl;
А вот чтение *(char**)ppm[0] - это легально. Однако легальность адресной арифметики в ppm[0][0] сомнительна...

Цитата Сообщение от Izual Посмотреть сообщение
C++
1
2
3
for(int i=0;i<3;i++){cout << fBufx[1] << "Ppm[" << i << "] Data = " << ((unsigned short*)ppm[1])[i] << " DataAdr: " << &ppm[1][i] << endl;}
for(int i=0;i<3;i++){cout << fBufx[2] << "Ppm[" << i << "] Data = " << ((float*) ppm[2])[i] << " DataAdr: " << &ppm[2][i] << endl;}
for(int i=0;i<3;i++){cout << fBufx[3] << "Ppm[" << i << "] Data = " << ((double*)ppm[3])[i] << " DataAdr: " << &ppm[3][i] << endl;}}
((unsigned short*)ppm[1])[i] - это легально.
((float*) ppm[2])[i] - это легально.
((double*)ppm[3])[i] - это легально.

Однако легальность адресной арифметики в ppm[1][i], ppm[2][i] и ppm[3][i] сомнительна...

Но к чему это все?
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
29.12.2016, 17:36
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Легальность адресной арифметики в ppm[0][i] сомнительна...
не сомнительна, а не верна в принципе, показывает то адресную арифметику int типа, а надо так:
C++
1
"DataAdr: " << &((unsigned short*)ppm[1])[i]
*по крайней мере так показывает правильно

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
В дело пошел reinterpret_cast. Запахло жареным...
Какая разница? Я указатели на начало массива привожу.. на данном этапе всё безопасно.

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Указатель на указатель тут только один - ppm.
угу)

По поводу остального: в топку

Добавлено через 8 минут
Кст, адрес на строку так:
C++
1
&((char**)ppm[0])[0]
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13229 / 6861 / 1827
Регистрация: 18.10.2014
Сообщений: 17,391
29.12.2016, 18:12
Цитата Сообщение от Izual Посмотреть сообщение
не сомнительна, а не верна в принципе,"
Речь идет не о том, что ото там "показывает", а о легальности адресной арифметики, выполненой через оператор [], еще до какого-либо доступа к памяти.

Цитата Сообщение от Izual Посмотреть сообщение
Какая разница? Я указатели на начало массива привожу.. на данном этапе всё безопасно.
Пока что все легально, но сам факт использования reinterpet_cast говорит, что дальше может начаться бредятина.

Именно дальше она у вас и началась.

Цитата Сообщение от Izual Посмотреть сообщение
По поводу остального: в топку
Никакого "в топку". Все, сказанное мною по поводу непределенного поведения - строго верно. Ваши упражнения никакого отношения к легальному С++ не имеют.

Цитата Сообщение от Izual Посмотреть сообщение
Кст, адрес на строку так:
C++
1
&((char**)ppm[0])[0]
Непонятно к чему это. &((char**)ppm[0])[0] эквивалентно просто (char**)ppm[0]. Это адрес нулевого элемента вашего массива mc.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
29.12.2016, 18:12

Создать динамический массив указателей
Создать динамический массив указателей для сохранения двумерного массива А в динамической памяти. Составить программу для подсчета...

Динамический массив с использованием указателей
Дан двумерный массив целых чисел размером , где m и n – заданные натуральные числа. Если в массиве есть такие две строки, что все элементы...

Динамический массив указателей на структуру
Не могу понять как выделить место под динамический массив указателей на структуру с помощью new. Все верно делаю? int lol = 1024; ...

Динамический массив указателей на объекты
вообщем была тут на форуме задача, в подробности вдаваться не буду, смысл сейчас заключается в том, чтобы создавать в цикле объекты, и в их...

Динамический массив указателей на объекты класса
Добрый вечер! Нужна помощь У меня имеется класс STROKA(вроде уже готовый,и все хорошо) Только вот никак не могу понять, как создать...


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

Или воспользуйтесь поиском по форуму:
29
Ответ Создать тему
Новые блоги и статьи
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru