Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Указатель на массив 
V
    Опции темы
Alexey91
  Дата 8.8.2010, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 195
Регистрация: 18.9.2008

Репутация: нет
Всего: нет



Здравствуйте!

Не могу понять как использовать указатель на массив (да и вообще в каких случаях это нужно)
Если смотреть по коду, то если x=a, программа будет виснуть почему не понимаю

Ведь а - это адрес начала массива
И я указателю на массив присваиваю адрес начала другого массива, но если написать амперсанд, то будет работать.


Код

#include <stdio.h>
#include <conio.h>

main()
{
 int (*x)[10];
 
 int *b;
 int a[10];
 
 int i;
 
 for(i=0; i < 10; i++)
 {
  a[i]=i; 
}        
 x=&a;
 b=a;
 
 printf("%d %d %d",a,x,b);
             
 getch();
 return 0;
}     
      


PM   Вверх
cmygeHm
Дата 9.8.2010, 08:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 96
Регистрация: 3.12.2008

Репутация: нет
Всего: -2



я вообще не видел никогда такой конструкции:
Код

 int (*x)[10];

А где Вы ее вычитали?
PM MAIL   Вверх
Annihilator
Дата 9.8.2010, 08:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


bytegrinder
**


Профиль
Группа: Участник
Сообщений: 493
Регистрация: 21.11.2006
Где: Омск

Репутация: 1
Всего: 3



Здесь будет различие в типах
int (*x)[10]; x - указатель на массив из 10 элементов типа int
int a[10]; a - указатель на первый элемент int-массива
т.е. в первом случае рассматривается адрес именно всего массива, т.е. в случае с переменной a адрес всего массива запишется как &a (именно то, что у тебя в коде)
ну а для компиляции выражения x=a надо чтобы a являлся 2-мерным массивом со второй размерностью, равной 10 в данном случае, т.е.
a[X][10]

Как-то так.


--------------------
Если вы не можете сделать хоpошyю пpогpаммy, сделайте, чтобы она по кpайней меpе выглядела хоpошо
PM ICQ   Вверх
Alexey91
  Дата 9.8.2010, 14:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 195
Регистрация: 18.9.2008

Репутация: нет
Всего: нет



Annihilator Думал, думал и никак не понял фразу "адрес всего массива". Как я понимаю массив представляет собой на носителе несколько ячеек памяти одного типа, адрес начала массива первая ячейка памяти. А вот адрес всего массива.. где он находится, к чему он конкретно относится? Не понятно(

А по поводу A[x][10] я понял так, что если присвоить x=A, то у x будет адрес элемента A[0][адрес всего массива]

но что такое адрес всего массива я никак понять не могу((
PM   Вверх
Annihilator
Дата 9.8.2010, 16:02 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


bytegrinder
**


Профиль
Группа: Участник
Сообщений: 493
Регистрация: 21.11.2006
Где: Омск

Репутация: 1
Всего: 3



Цитата(Alexey91 @  9.8.2010,  18:53 Найти цитируемый пост)
Annihilator Думал, думал и никак не понял фразу "адрес всего массива". Как я понимаю массив представляет собой на носителе несколько ячеек памяти одного типа, адрес начала массива первая ячейка памяти. А вот адрес всего массива.. где он находится, к чему он конкретно относится? Не понятно(

Я имел в виду что при таком объявлении:
int (*x)[10]
x - "указатель на массив из десяти int", т.е. имеет тип int (*)[10]
а если так:
int x[10], то x имеет тип "int[10]"

т.е. если в первом случае инкрементировать x, то мы не попадем на следующий элемент массива, значение x увеличится на 10*sizeof(int), а не на sizeof(int)
т.е. x - имеет тип "указатель на массив из 10 целых чисел"

Типы разные, в этом все дело

Кстати, вот


Это сообщение отредактировал(а) Annihilator - 9.8.2010, 16:29


--------------------
Если вы не можете сделать хоpошyю пpогpаммy, сделайте, чтобы она по кpайней меpе выглядела хоpошо
PM ICQ   Вверх
baldina
Дата 9.8.2010, 17:13 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Код

int A[10]; // A - массив из 10 элементов int (не указатель!). здесь компилятор выделяет память под 10 элементов типа int
int *p; // p - указатель на int (может в том числе указывать на какой-либо элемент в каком-либо массиве. здесь компилятор выделяет память под переменную-указатель, p хранит адрес.
p = A; // присваиваем p адрес начала массива, он же - адрес элемента c индексом 0. А в данном случае (неявно) преобразуется в тип "указатель на челое"
p = &A[0]; // то же самое

A = p; // Error: А не является l-value. Ему нельзя присваивать значения.


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

зачем нужно:
1. перебрать все элементы в коллекции
Код

const int N=10;
int A[N];
for (int *p = A; p != A+N; ++p)
{
  // *p - текущий элемент массива
}


2. Передать адрес начала массива в функцию:
Код

void print_array (int *array, int size)
{
   for (int i=0; i < size; ++i)
     std::cout << array[i] << std::endl;

/*
   или:
   for (int *p=array; p != array+size; ++p)
     std::cout << *p << std::endl;
*/
}

int main ()
{
  const int N=10;
  int A[N] = {0,1,2,3,4,5,6,7,8,9};
  print_array (A, N);
}


PM MAIL   Вверх
Alexey91
Дата 9.8.2010, 17:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 195
Регистрация: 18.9.2008

Репутация: нет
Всего: нет



Annihilator 
Угу!
Мне как раз компилятор и выдал:
16 cannot convert `int[10]' to `int (*)[10]' in assignment 
А я никак понять не мог.

Только не понимаю почему нужно перед а ставить апмерсанд, ведь при а и &а будет выводится один и тот же адрес.
Где происходит различие, что одно является адреса начала, а другое адресом всего массива)

т.е. амперсандом мы как бы получаем &int[10]

Я понял все, что ты сказал по аналогии с обычными переменными:

int d,*e;

d=1;
e=&d;

также с массивами

int (*a)[10], b[10];

b[10]={0,1,2,3,4,5,6,7,8,9};
a=&b;
Код


#include <stdio.h>
#include <conio.h>
main()
{
 int (*x)[10];
 int a[10];
 int i;
 for(i=0; i < 10; i++)
 {
  a[i]=i; 
}        
 x=&a;
 printf("%d %d %d",x,*x,**x);
             
 getch();
 return 0;
}     


Хм.. а почему я получаю значение элемента а[0] только после двойного разыменования?
Если не трудно, можешь написать.. если мы берем х, то получаем
если мы берем *x
... **х

 smile 


Baldina, спасибо !  smile 



Это сообщение отредактировал(а) Alexey91 - 9.8.2010, 18:15
PM   Вверх
boostcoder
Дата 9.8.2010, 17:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



не занимайтесь велоизобретательством, используйте контейнеры.
PM WWW   Вверх
Annihilator
Дата 9.8.2010, 18:43 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


bytegrinder
**


Профиль
Группа: Участник
Сообщений: 493
Регистрация: 21.11.2006
Где: Омск

Репутация: 1
Всего: 3



Цитата(Alexey91 @  9.8.2010,  21:49 Найти цитируемый пост)
Только не понимаю почему нужно перед а ставить апмерсанд, ведь при а и &а будет выводится один и тот же адрес

Адрес один, да типы разные.
Цитата(Alexey91 @  9.8.2010,  21:49 Найти цитируемый пост)
Где происходит различие, что одно является адреса начала, а другое адресом всего массива)

Если ты опреляешь переменную как массив
int a[10] - здесь a еще не указатель

иначе говоря a является указателем, при использовании без скобок [], допустим как аргумент функции
(в соответствии с п.4.2.1 Стандарта)
На лицо одномерный масив,
и с помощью такого указателя мы можем двигаться поэлементно

если же мы объявляем
int (*x)[10];
то в этом объявлении x - уже указатель, а если его использовать без [] - получается что x становится указателем на указатель
и мы можем двигать не поэлементно а "помассивно", т.е. можем использовать для построчного считывания 2d-массива

Код

    int a[3][4];
    for(int i=0; i < 3; i++)
    {
        for (int j=0; j < 4; j++)
            a[i][j]=i*2+j*3; 
    } 

    int (*x)[4];
    x=a;
    ++x; //перепрыгиваем строку

   int a_2_1 = *(*(x+1)+1) // двойное разыменовывание


Объяснил как мог...

Это сообщение отредактировал(а) Annihilator - 9.8.2010, 18:54


--------------------
Если вы не можете сделать хоpошyю пpогpаммy, сделайте, чтобы она по кpайней меpе выглядела хоpошо
PM ICQ   Вверх
toxx
Дата 9.8.2010, 20:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 653
Регистрация: 4.3.2009
Где: НН

Репутация: 4
Всего: 13



Цитата

не занимайтесь велоизобретательством, используйте контейнеры. 

если пользоваться сразу контейнерами, не будешь знать множество ньюансов их создания.имхо
PM MAIL   Вверх
boostcoder
Дата 9.8.2010, 21:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



Цитата(toxx @ 9.8.2010,  20:24)
Цитата

не занимайтесь велоизобретательством, используйте контейнеры. 

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

ок. перефразирую: не занимайтесь велоизобретательством в реальных программах.
PM WWW   Вверх
baldina
Дата 10.8.2010, 11:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Alexey91, при объявлении
Код
int A[10];
выражения A и &A - синонимы и значения их равны &A[0]. 
Код

int x; // переменная типа int, хранит значение типа int. для получения адреса переменной используется &x
int *x; // указатель на int. хранит адрес. для доступа к значению по этому адресу используется разыменование *x
int **x; // указатель на указатель на int. хранит адрес, по которому расположен указатель. для доступа к значению int используется **x

про это в книжках пишут, почитай...
тут, например, пункт 5.3
PM MAIL   Вверх
Alexey91
Дата 12.8.2010, 10:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 195
Регистрация: 18.9.2008

Репутация: нет
Всего: нет



Извиняюсь, за свое отсутствие

Annihilator, чувствую что понял (хотя чувства обманчивы )...

Переменная x является указателем на указатель, и при добавлении к переменной a амперсанда мы получаем адрес, который является указателем на адрес начала массива. И при увеличении адреса х, мы переместимся не на элемент массива, а на весь массив.

Кстати, чтобы не путаться адрес и указатель означают же одно и то же?

Есть переменная-указатель, которая хранит адрес 
это же аналогично
Есть переменная-указатель, которая хранит указатель?

И.. если у нас массивы любые, двумерные, n-мерные располагаются последовательно в памяти (т.е. например вызов элемента массива a[3][4] означает то же самое, что и a[0][12]). То зачем тогда были введены все эти размерности???

Baldina
Цитата


Alexey91, при объявлении
Код
int A[10];
выражения A и &A - синонимы и значения их равны &A[0]. 
Код

int x; // переменная типа int, хранит значение типа int. для получения адреса переменной используется &x
int *x; // указатель на int. хранит адрес. для доступа к значению по этому адресу используется разыменование *x
int **x; // указатель на указатель на int. хранит адрес, по которому расположен указатель. для доступа к значению int используется **x

про это в книжках пишут, почитай...
тут, например, пункт 5.3



Я имел ввиду в контексте программы), так мне ясно, что является указателем, а что указателем на указателем.
У меня тогда возникла путаница, что a (адрес начала массива) и &a имеют одинаковый адрес
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

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

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1072 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.