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

Указатели и масивы - C++

Восстановить пароль Регистрация
 
fuelcs
12 / 12 / 0
Регистрация: 23.01.2013
Сообщений: 143
23.01.2013, 16:12     Указатели и масивы #1
Добрый день.
Помогите пожалуйста разобраться с указателями.

Есть рабочий код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const int n=5;
    int a [n][n];
 
    int k=1;
    for (int i=0;i<n;i++)
    {
        for (int j=0;j<n;j++)
        {
            a[i][j]=k++;
        }
    }
 
    for (int i=0;i<n;i++)
    {
        for (int j=0;j<n;j++)
        {
            cout << *(*(a + i) + j) << " ";
        }
        cout << "\n";
    }
который инициализирует массив и выводит его на экран.

Насколько я понимаю а - есть указатель на указатель, исходя из выражения *(*(a + i) + j)

Вопрос: почему если я объявляю функцию:

C++
1
2
3
4
void func(int** a, int n)
       {
 
       }
и обращаюсь к ней как:

C++
1
 func(a,n);
компилятор выдает ошибку?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.01.2013, 16:12     Указатели и масивы
Посмотрите здесь:

C++ Масивы С/С++
C++ Масивы
C++ 2-D масивы.
Указатели/масивы C++
Масивы C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,919
Записей в блоге: 2
Завершенные тесты: 1
23.01.2013, 16:25     Указатели и масивы #2
Цитата Сообщение от fuelcs Посмотреть сообщение
исходя из выражения *(*(a + i) + j)
а исходя из этого:
C++
1
std::cout << *(&a[0][0]+i*n+j) << " ";
можно сделать вывод, что это одномерный массив интерпретируемый как двумерный
fuelcs
12 / 12 / 0
Регистрация: 23.01.2013
Сообщений: 143
23.01.2013, 18:16  [ТС]     Указатели и масивы #3
Цитата Сообщение от Croessmah Посмотреть сообщение
а исходя из этого:
C++
1
std::cout << *(&a[0][0]+i*n+j) << " ";
можно сделать вывод, что это одномерный массив интерпретируемый как двумерный
Насколько я понял a[0][0] - это указатель на первый элемент массива?

Код:

C++
1
cout << *(*a+i*n+j) << " ";
идентичен вашему? В чем разница между &a[0][0] и *a ?

Я еще попробовал записать так:

C++
1
cout << *(*(&a[0]+i) + j) << " ";
Что такое a[0] ?
Shepard90
5 / 5 / 0
Регистрация: 18.10.2010
Сообщений: 140
23.01.2013, 18:40     Указатели и масивы #4
a[0][0] это уже не указатель на первый элемент. а само значение. запись &a[0] = a - вы за счет индексации разименовали и опять же получили адрес. Хочу сказать, что индексирование это по сути то же самое, что и разименование.
MickeyBlueEyes
Студент
 Аватар для MickeyBlueEyes
120 / 131 / 12
Регистрация: 07.04.2011
Сообщений: 503
23.01.2013, 18:59     Указатели и масивы #5
&a[0][0] - адресс первого елемента массива.
a[0] - это адресс начала a[0][0]
Shepard90
5 / 5 / 0
Регистрация: 18.10.2010
Сообщений: 140
23.01.2013, 19:07     Указатели и масивы #6
Цитата Сообщение от MickeyBlueEyes Посмотреть сообщение
&a[0][0] - адресс первого елемента массива.
a[0] - это адресс начала a[0][0]
??? &a[0][0] и a[0] это одно и то же. накидайте небольшой код и посмотрите результат обоих вариантов применения операторов к массиву - в выоде будет один и тот же адрес
fuelcs
12 / 12 / 0
Регистрация: 23.01.2013
Сообщений: 143
23.01.2013, 19:08  [ТС]     Указатели и масивы #7
Цитата Сообщение от MickeyBlueEyes Посмотреть сообщение
&a[0][0] - адресс первого елемента массива.
a[0] - это адресс начала a[0][0]
Что значит a[0] - это адресс начала a[0][0] ?

И что такое a и *a ?
Shepard90
5 / 5 / 0
Регистрация: 18.10.2010
Сообщений: 140
23.01.2013, 19:10     Указатели и масивы #8
Цитата Сообщение от Shepard90 Посмотреть сообщение
??? &a[0][0] и a[0] это одно и то же. накидайте небольшой код и посмотрите результат обоих вариантов применения операторов к массиву - в выоде будет один и тот же адрес
MickeyBlueEyes, хотя ваши слова вроде как не противоречат этому
MickeyBlueEyes
Студент
 Аватар для MickeyBlueEyes
120 / 131 / 12
Регистрация: 07.04.2011
Сообщений: 503
23.01.2013, 19:24     Указатели и масивы #9
Цитата Сообщение от fuelcs Посмотреть сообщение
Что значит a[0] - это адресс начала a[0][0] ?
Да, если написать так *a[0], то с адресса a[0] вытянется значения a[0][0], если так *(a[0] + 1), то значение из a[0][1].

Цитата Сообщение от fuelcs Посмотреть сообщение
И что такое a и *a ?
Одно и тоже, это адресс a[0][0];

Цитата Сообщение от Shepard90 Посмотреть сообщение
MickeyBlueEyes, хотя ваши слова вроде как не противоречат этому
Ну да)
fuelcs
12 / 12 / 0
Регистрация: 23.01.2013
Сообщений: 143
23.01.2013, 19:27  [ТС]     Указатели и масивы #10
Цитата Сообщение от Shepard90 Посмотреть сообщение
??? &a[0][0] и a[0] это одно и то же. накидайте небольшой код и посмотрите результат обоих вариантов применения операторов к массиву - в выоде будет один и тот же адрес
C++
1
2
3
4
for (int i=0;i<n;i++)
{
    cout << &a[i] << "\n";
}
выводит адрес первого элемента каждой строки
MickeyBlueEyes
Студент
 Аватар для MickeyBlueEyes
120 / 131 / 12
Регистрация: 07.04.2011
Сообщений: 503
23.01.2013, 19:35     Указатели и масивы #11
Кстати сам суть вопроса в силе:
C++
1
func(a,n);
Ну на сколько я понял, это контролирует уже сам компилятор, в ф-ции ожидается что будет передаватся указатель на указатели, а передаётся массив, но вообще банально в стек ложится адресс начала массива вроде так да.
Если ф-цию вызывать так:
C++
1
func(a,n)
То компилятор походу понимает это как передача массива в ф-цию и происходит ошибка, а хотя это адресс начала массива ф-ции.
Если параметр обьявить как
C++
1
void func(int a[][10]){}
То ошибки не будет, первую скобку можна опустить, но размер второй ячейки должен соответсовать, что затрудняет работу, поэтому обычно передают указатель на указатели.
Shepard90
5 / 5 / 0
Регистрация: 18.10.2010
Сообщений: 140
23.01.2013, 20:04     Указатели и масивы #12
Цитата Сообщение от fuelcs Посмотреть сообщение
for (int i=0;i<n;i++)
{
cout << &a[i] << "\n";
}
выводит адрес первого элемента каждой строки
Вернее первого столбца

Добавлено через 9 минут
Цитата Сообщение от Shepard90 Посмотреть сообщение
Цитата Сообщение от fuelcs Посмотреть сообщение
for (int i=0;i<n;i++)
{
cout << &a[i] << "\n";
}
выводит адрес первого элемента каждой строки
Вернее первого столбца
Ой извиняюсь. Адреса элементов первого столбца. Очитался все верно

Добавлено через 3 минуты
fuelcs, а зачем вы пользуте статические массивы? Если уж вам и необходимо применять указатели, разименования и пр., то юзали бы динамические - намного понятнее и универсальнее, чем использовать статические вкупе с указателями.

Добавлено через 10 минут
C++
1
2
3
4
5
6
7
8
9
10
11
int N,M;
cin>>N;
cin>>M;
int ** Matrix=new int*[N];//создаем указатель на массив указателей
for(int i=0;i<N;i++){
    Matrix[i]=new int[M];//каждому указателю массива Matrix[i] присваиваем массив чисел
    for(int j=0;j<M;j++)
        Matrix[i][j]=0;
}
f(Matrix,N,M)
delete [] Matrix; //не забываем высвобождать выделенную память
C++
1
void f(int ** a, int n, int m){}
fuelcs
12 / 12 / 0
Регистрация: 23.01.2013
Сообщений: 143
23.01.2013, 20:09  [ТС]     Указатели и масивы #13
Я только разбираюсь с указателями, пока с динамическими массивами не умею работать.

По сути, я хотел передать в функцию массив через указатели.

Подскажите, я правильно понимаю суть:
двухмерный массив это структура которая состоит из одномерных массивов, на первый элемент которых указывает массив указателей, и в свою очередь на первый указатель массива указывает указатель?

На примере:
а - указатель на первый указатель массива указателей
*а - адрес первого указателя из массива.

Если так, то как мне передать в функцию тот указатель?
fuelcs
12 / 12 / 0
Регистрация: 23.01.2013
Сообщений: 143
26.01.2013, 18:48  [ТС]     Указатели и масивы #14
Получилось так:

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
void func (int** c, int m, int n)
{
    for (int i=0;i<m;i++)
    {
        for (int j=0;j<n;j++)
        {
            cout << setw(3) << *(*(c+i)+j);
        }
        cout << "\n";
    }
}
 
int main()
{
    const int m=4;
    const int n=5;
    int a [m][n]={0};
    int* b[m];
    
    for (int i=0;i<m;i++)
    {
        //b[i]=a[i];        Вариант 1
        //b[i]=&a[i][0];    Вариант 2
        b[i]=*(a+i);//      Вариант 3
    }
 
    int** c=&b[0];
 
    for (int i=0;i<m;i++)
    {
        for (int j=0;j<n;j++)
        {
            a[i][j]=i*n+j+1;
            cout << setw(3) << a[i][j];
        }
        cout << "\n";
    }
 
    cout << "\n";
 
    func(c,m,n);
 
    return 0;
}
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,919
Записей в блоге: 2
Завершенные тесты: 1
26.01.2013, 20:55     Указатели и масивы #15
C++
1
2
3
4
5
6
7
8
template<typename T,int N,int M>
void foo(T (&arr)[N][M]){
    
}
int main(){
    int arr[12][30];
    foo(arr);
}
fuelcs
12 / 12 / 0
Регистрация: 23.01.2013
Сообщений: 143
27.01.2013, 00:16  [ТС]     Указатели и масивы #16
Цитата Сообщение от Croessmah Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
template<typename T,int N,int M>
void foo(T (&arr)[N][M]){
    
}
int main(){
    int arr[12][30];
    foo(arr);
}
это работает как для статических так и для динамических массивов?

и не могли бы вы скинуть ссылочку на хорошую статью по шаблонах?
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,919
Записей в блоге: 2
Завершенные тесты: 1
27.01.2013, 00:31     Указатели и масивы #17
Цитата Сообщение от fuelcs Посмотреть сообщение
это работает как для статических так и для динамических массивов?
Для "динамического" не пойдет.
статический массив и "динамический" это разные вещи.
Второй - это, как правило, просто указатель на участок памяти и всё, ну или контейнер(обертка).
Цитата Сообщение от fuelcs Посмотреть сообщение
на хорошую статью по шаблонах?
Тут скорее нужно книги читать.
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
27.01.2013, 04:52     Указатели и масивы #18
fuelcs, возможно в этой теме уже упомянули, но по поводу массивов\указателей в С\С++ есть "забавная" вещь. Имя массива почти во всех случаях неявно преобразуется в указатель на первый элемент. Например такой код:
C++
1
2
3
4
5
6
void f(int * array) { // ... }
 
int main{
   int array[5];
   f(array);
}
правильный. Но это правило не применяется рекурсивно. Т.е. такой код уже не корректен:
C++
1
2
3
4
5
6
void f(int ** array) { // ... }
 
int main{
   int array[5][5];
   f(array);
}
Т.е. имя двумерного массива не может преобразоваться к указателю на указатель на первый элемент. Только к указателю на массив. Т.е. такой такой код корректен:
C++
1
2
3
4
5
6
void f(int (* array)[5]) { // ..}
 
int main{
   int array[5][5];
   f(array);
}

Не по теме:

Вот такие проги.



Добавлено через 7 минут
Цитата Сообщение от gray_fox Посмотреть сообщение
Вот такие проги.

Не по теме:

"Вот такие пироги" ну да)))

MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.01.2013, 23:07     Указатели и масивы
Еще ссылки по теме:

Масивы C++
C++ Масивы
C++ масивы

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

Или воспользуйтесь поиском по форуму:
fuelcs
12 / 12 / 0
Регистрация: 23.01.2013
Сообщений: 143
28.01.2013, 23:07  [ТС]     Указатели и масивы #19
Цитата Сообщение от Shepard90 Посмотреть сообщение
int N,M;
C++
1
2
3
4
5
6
7
8
9
10
cin>>N;
cin>>M;
int ** Matrix=new int*[N];//создаем указатель на массив указателей
for(int i=0;i<N;i++){
* * Matrix[i]=new int[M];//каждому указателю массива Matrix[i] присваиваем массив чисел
* * for(int j=0;j<M;j++)
* * * * Matrix[i][j]=0;
}
f(Matrix,N,M)
delete [] Matrix; //не забываем высвобождать выделенную память
Высвобождать выделенную память нужно так (для двухмерного массива):
C++
1
delete [] Matrix;
или так:
C++
1
2
3
for(int i=0;i<N;i++)
* * delete [] Matrix [i];
delete [] Matrix;
??
Yandex
Объявления
28.01.2013, 23:07     Указатели и масивы
Ответ Создать тему
Опции темы

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