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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 23, средняя оценка - 4.65
G-Cat
16 / 16 / 1
Регистрация: 15.03.2009
Сообщений: 94
#1

работа с указателями - C++

08.05.2009, 06:59. Просмотров 3007. Ответов 17
Метки нет (Все метки)

небольшая проблемка, никак не могу разобраться с указателями. Я так понял что создавая массив лучше если сразу сдалешь на него указатель и будешь работать с ним, нежели с самим массивом, тип так экономичнее для ресурсов компа, я ведь правильно понял?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <cstdlib>
#include <iostream>
#include <stdio.h>
 
short int const n = 3;
 
using namespace std;
 
int main(int argc, char *argv[])
{
    int z[n];
    int *a = &z[0];
    
    
    for (short int i = 0; i < n; i++)
        cin >> *a++;
 
    for (short int i = 0; i < n; i++)
        cout << *a++ << endl;
    
    system("PAUSE");
    return EXIT_SUCCESS;
}
при вводе, например: 1, 2, 3, прога выводит: 2, 2293576, 1987762951. Я так понял указатель вышел за пределы массива и 2 - это последний элемент массива, т.к. у меня строгое < 3, а дальше просто изгаляется как хочет. В чем проблема, акромя кривизны моих рук?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.05.2009, 06:59
Здравствуйте! Я подобрал для вас темы с ответами на вопрос работа с указателями (C++):

Работа с указателями - C++
Всем здравия. Нужна ваша помощь. Есть задание по С++. К сожалению работала в основном по С# да и с указателями не совсем лажу. Может кто...

работа с указателями - C++
Вспоминаю с++ и в связи с этим возникло несколько вопросов. 1) если сделать так : myobj *obj = new myobj(); то потом можно...

Работа с указателями - C++
#include &lt;iostream&gt; #include &lt;cstdio&gt; #include &lt;iomanip&gt; using namespace std; int main() { int i;float f;long int l;double d;...

работа с указателями - C++
Как ПРАВИЛЬНО передать в функцию, массив, используя адресацию? Программа находит в массиве слово и перед ним вставляет какое то слово, то...

Работа с указателями - C++
Написать программу, в которой выполнить следующие действия: 1) Описать указатели на все известные типы данных; 2. Выполнить для каждого...

работа с указателями - C++
Помогите решить задачу в С++ (я в этом начиющий): 1)Из положительных значений двух целочисленных массивов различной размерности...

17
kazak
3035 / 2356 / 155
Регистрация: 11.03.2009
Сообщений: 5,402
Завершенные тесты: 1
08.05.2009, 07:45 #2
Во первых, имя массива и есть указатель на первый элемент. Во вторых, если так хочешь, то a = z; . И в третьих, *(a++).

Добавлено через 6 минут 44 секунды
Точнее в третьих *(a+i).
1
G-Cat
16 / 16 / 1
Регистрация: 15.03.2009
Сообщений: 94
08.05.2009, 07:48  [ТС] #3
т.е. правильно будет выглядеть так?:
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
#include <cstdlib>
#include <iostream>
#include <stdio.h>
 
short int const n = 3;
 
using namespace std;
 
int main(int argc, char *argv[])
{
    int z[n];
    int *a = z;
    
    
    for (short int i = 0; i < n; i++)
        cin >> *(a++);
        
    a = z;  
 
    for (short int i = 0; i < n; i++)
        cout << *(a++) << endl;
    
    system("PAUSE");
    return EXIT_SUCCESS;
}
в чем тогда роль знака "&" в выражении *a = &z[0];? Зачем он вообще нужен в указателях?
Почему именно *(a++)? без скобок и так работает ведь. В них вроде же необходимость только если нужно записать какоее нибудь хитрое увеличение указателя, например: *(a+2^n)
0
kazak
3035 / 2356 / 155
Регистрация: 11.03.2009
Сообщений: 5,402
Завершенные тесты: 1
08.05.2009, 08:32 #4
* имеет больший приоритет, те при *a++ сначала разименовывается указатель, потом инкремент. Далее я поправился, что указатель лучше не изменять, можно запутаться, применяй *(a+i).
Потом z - указатель, z[i] - переменная, &z[i] - ссылка на переменную(аналог указателя).
1
G-Cat
16 / 16 / 1
Регистрация: 15.03.2009
Сообщений: 94
08.05.2009, 08:42  [ТС] #5
огромное СПАСИБО!
А как работать с двумерными массивами?...я вот тут накорябал, но не работает:
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
#include <cstdlib>
#include <iostream>
#include <stdio.h>
 
short int const n = 3;
short int const m = 4;
 
using namespace std;
 
int main(int argc, char *argv[])
{
        int z[n][m];
        int *a = z;
        
        for (short int i=0; i<n*m; i++)
             cin >> *(a+i);
                
        a = z;  
 
        for (short int j=0; j<n; j++)
        {
             for (short int i=0; i<n; i++)
                  cout << *(a+i) << "\t";
             cout << endl;
        }
        
    system("PAUSE");
    return EXIT_SUCCESS;
}
...или просто надо двумерный массив представлять одномерным и работать уже с ним?
0
kazak
3035 / 2356 / 155
Регистрация: 11.03.2009
Сообщений: 5,402
Завершенные тесты: 1
08.05.2009, 09:21 #6
Зачем такие сложности?
0
CyBOSSeR
Эксперт С++
2303 / 1673 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
08.05.2009, 09:24 #7
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
#include <iostream>
 
const int n = 3;
const int m = 4;
 
using namespace std;
 
int main(int argc, char *argv[])
{
  int z[n][m]; // Имя любого массива (хоть двумерного, хоть 10-мерного) является указателем на первый элемент
 
  for(int i = 0; i < n; ++i)
    for(int j = 0; j < m; ++j)
      cin >> *(*(z + i) + j); //
  
 
  for (int i=0; i< n; i++)
  {
    for (int j=0; j < m; j++)
      cout << *(*(z + i) + j) << "\t";
    cout << endl;
  }
 
  system("PAUSE");
  return EXIT_SUCCESS;
}
Просто запомни что имя массива является указателем на первый элемент, следовательно ты можешь с именем массива обращаться как с указателем.
В случае с двумерным массивом он (массив) грубо говоря является массивом указателей на массивы чисел, т.е.
C++
1
2
3
4
5
int z[3][3] = {
  {1, 2, 3},
  {4, 5, 6},
  {7, 8, 9}
};
можно представить как:
z[1] указатель на {1, 2, 3}
z[2] указатель на {4, 5, 6}
z[3] указатель на {7, 8, 9}

Т.е. z[i] есть указатель на i-ую строку в массиве.

Когда ты пишешь z[i][j] идет обращений к j-му элементу i-ой строки.

Теперь давай разберемся с последовательностью выполнения такого вот оператора: *(*(z + i) + j) (который полностью эквивалентен оператору z[i][j])
1. z + i -получаем указатель типа int** на i-ую строку
2. *(z + i) - получаем строку (которая по сути является одномерным массивом), т.е. указатель типа int*
3. *(z + i) + j - получаем указатель на j-ый элемент i-ой строки, т.е. указатель типа int*
4. *(*(z + i) + j) - собственно получаем сам j-ый элемент i-ой строки, т.е. int.

И еще совет: не пользуйся типами short int, long double без необходимости, т.к. когда ты пишешь
C++
1
short int n = 4;
4 рассматривается как тип int, а следовательно компилятору приходится эту четверку преобразовывать к типу short int, везде где можно используй стандартный типы:
C++
1
bool, char, int, double
1
Deicider
96 / 52 / 1
Регистрация: 18.03.2009
Сообщений: 273
08.05.2009, 09:28 #8
Такой код действительно не будет работать. В одномерном массиве переменная хранит адрес первого элемента. Двумерный массив представляет собой массив указателей, каждый из которых указывает на первый элемент соответствующего одномерного массива. Переменные *(a+i) хранят как значения элементов массивов, так и указатели на их начало, поэтому записывая произвольные значения в *(a+i), ты меняешь значения указателей и они уже не указывают на реальный массив в памяти.
1
G-Cat
16 / 16 / 1
Регистрация: 15.03.2009
Сообщений: 94
08.05.2009, 10:11  [ТС] #9
Огромное спасибо всем, очень понятно и по делу проконсультировали. В который раз рад что зарегистрировался здесь =)
0
Rififi
2359 / 1052 / 44
Регистрация: 03.05.2009
Сообщений: 2,656
08.05.2009, 11:21 #10
G-Cat,
... имя массива и есть указатель на первый элемент ...
... Имя любого массива (хоть двумерного, хоть 10-мерного) является указателем на первый элемент ...
... запомни что имя массива является указателем на первый элемент ...
... Двумерный массив представляет собой массив указателей ...

а теперь - правильный ответ. (((Ж

имя массива - это не указатель ни на первый элемент, ни на последний, ни на какой-либо еще, и никогда им не было.
Фраза про то, что двумерный массив = массив указателей особенно жгуча.
массив - это сущность языка c/c++, которая характеризуется двумя параметрами: тип и размер. всё.

а всё, что тут ту услышал про "указатели" - это от незнания Стандарта, в частности правила Array-to-pointer conversion

Я так понял что создавая массив лучше если сразу сдалешь на него указатель и будешь работать с ним, нежели с самим массивом, тип так экономичнее для ресурсов компа, я ведь правильно понял?
для "ресурсов компа" особой разницы нет - адрес он и в Африке адрес. А при операциях адресной арифметики указатель может быть удобнее.
1
kazak
3035 / 2356 / 155
Регистрация: 11.03.2009
Сообщений: 5,402
Завершенные тесты: 1
08.05.2009, 12:40 #11
Массивы и указатели в С++ тесно связаны и могут быть использованы почти эквивалентно. Имя массива можно понимать как константный указатель. Указатели можно использовать для выполнения любой операции, включая индексирование масива.
Предположим, что объявлены массивы целых чисел b[5] и целая переменная указатель bPtr. Поскольку имя массива(без индекса) является указателем на первый элемент массива, мы можем задать указателю bPtr адреспервого элемента массива b с помошью оператора
bPtr = b;
Это эквивалентно присваиванию адреса первого элемента массива следующим образом
bPtr = &b[0]
Сослаться на элемент массива b[3] можно с помощью выражения указателя
*(bPtr + 3)
В приведенном выражении 3 является смещением указателя. Когда указатель указыает на начало массива, смещение показывает, на какой элемент массива должна быть ссылка, так что значение ссмещения эквивалентно индексу массива. Предыдущую запись называют записью указатель-смещение. Скобки необходимы, потому что приоритет * выше, чем приоритет +. Без скобок верхнее выражение прибавило бы 3 к значению выражения *bPtr (т.е. 3 было бы прибавленно к b[0] в предположении, что bPtr указывает на начало массива). Поскольку элемент массива может быть указан указателем выражением, адрес
&b[3]
может быть записан также выражением указтелем
bPtr + 3
Сам массив можно рассматривать как указатель и использовать в арифметике указателей. Например, выражение
*(b + 3)
тоже ссылается на элемент массива b[3]. Вообще все выражения с индексами массива могли бы быть записаны с помощью указателей и смещений. В этом случае запись указатель-смещение применялась бы к имени массива как к указателю. Заметим, что предыдущий оператор никоим образом не модифицирует имя массива; b продолжает указывать на первый элемент массива.


Источник: Х.Дейтел, П.Дейтел "Как программировать на С++"
Rififi, и где мы переврали?
1
G-Cat
16 / 16 / 1
Регистрация: 15.03.2009
Сообщений: 94
08.05.2009, 14:13  [ТС] #12
странно, у меня тоже книга Дейтелов (пятое малое издание), но там не так понятно и доходчиво объяснено...

пока вы тут все не разбежались. Я не понимаю как передавать массив или указатель в функцию. Не могли бы помочь?
0
stolyars
10 / 10 / 1
Регистрация: 24.12.2008
Сообщений: 32
08.05.2009, 14:20 #13
C++
1
int search(int*ptr,int array[]);//прототип
1
G-Cat
16 / 16 / 1
Регистрация: 15.03.2009
Сообщений: 94
08.05.2009, 14:22  [ТС] #14
...ток хотел исправить свой предыдущий меседж

я хотел спросить не как одномерный массив передать, а двумерный...ну или более.
0
stolyars
10 / 10 / 1
Регистрация: 24.12.2008
Сообщений: 32
08.05.2009, 14:27 #15
раз уж тема про указатели дабы не плодить еще тем хочу спросить:
C++
1
cin >> *(a++)
и
C++
1
cin>>a[i]
("а"-это указатель).чем отличается в работе?ведь так и так работает...вопрос касаемо указателей на массив...

Добавлено через 2 минуты 11 секунд
как и одномерный ток размер одного индекса указать нужно
C++
1
int search(int array[10][]);
если не ошибаюсь
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.05.2009, 14:27
Привет! Вот еще темы с ответами:

работа с указателями - C++
#include &lt;iostream&gt; using namespace std; int main() { char *res=&quot;&quot;; res=&quot;1&quot;; res=&quot;2&quot;; ...

Работа с указателями - C++
Помогите пожалуйста объяснить, не понимаю почему число присваемое через указатель *А в кавычках, и равны ли *А и просто А??? char *A =...

Работа с указателями - C++
Расскажите как работает каждая строка в коде char *A = &quot;123456789&quot;; unsigned B = 1; char *X = A + B; char *Y = A - (-...

Работа с указателями - C++
1. Написать функцию, принимающую в качестве параметра указатель на первый символ строки и возвращающую адрес первого символа этой же...


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

Или воспользуйтесь поиском по форуму:
15
Yandex
Объявления
08.05.2009, 14:27
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru