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

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

Войти
Регистрация
Восстановить пароль
 
dimon1984
40 / 38 / 0
Регистрация: 22.01.2011
Сообщений: 670
#1

Указатели :) - C++

02.03.2011, 01:19. Просмотров 955. Ответов 13
Метки нет (Все метки)

Вроде понимаю что такое указатели, что это адрес в памяти, знаю что к примеру int* x = &y это в "x" тоже значение, что и в "y". Когда смотрю код, то вроде понятно, а когда пишу чтото, то бывает немного не понятно.
К примеру как назначить указатель на двумерный массив?
m[5][5] ? Чтото типа **(указатель на указатель?)
C++
1
2
3
4
5
6
7
8
9
int main ( )
{
    char q1[2][6] = {"hello","world"};
    char* p = *q1;
    cout << p << endl;
 
    system("pause");
    return 0;
}
Здесь только hello выводит. А как чтобы hello world вывело?
Если можно, то поконкретней, разжованней, потому что эта тема сложная для самостоятельного изучения.
И обьясните плиз про синтаксис ** (указатель на указатель) с простым примером плиз.
** относится к двумерному массиву? [][] ?

Добавлено через 37 минут
и что значит такой синтаксис? *(*...)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.03.2011, 01:19     Указатели :)
Посмотрите здесь:

C++ Указатели в С++
Указатели C++
Указатели C++
Указатели C++
на указатели C++
C++ Указатели
C++ указатели в С
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
silent_1991
Эксперт C++
4949 / 3025 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
02.03.2011, 01:27     Указатели :) #2
Цитата Сообщение от dimon1984 Посмотреть сообщение
Вроде понимаю что такое указатели
в том-то и дело, что вроде...
Начать с того, что на самом деле указатель - это переменная, способная хранить адрес другой переменной.

Цитата Сообщение от dimon1984 Посмотреть сообщение
к примеру int* x = &y это в "x" тоже значение, что и в "y"
В x никак не может быть то же значение, что и в y. В x хранится адрес переменной y. Т.е. значением x является адрес в памяти, по которому расположены данные, записанные в y.

Цитата Сообщение от dimon1984 Посмотреть сообщение
К примеру как назначить указатель на двумерный массив?
Стандартный двумерный массив не является массивом указателей, поэтому присвоить m двойному указателю не получится. Присвоение должно быть таким:
C++
1
2
char m[2][6] = {"hello", "world"};
char (*ptr)[6] = m;
Вторая строка означает: мы объявляем указатель ptr на массив из 6 элементов (если менее строго - массив массивов из 6 элементов) и связываем его с m.
Выводить тогда следует так:
C++
1
std::cout << m[0] << ", " << m[1] << "!" << std::endl;
Т.е. сначала вывели 1 строку, потом вторую. Вывести сразу обе не получится.

Цитата Сообщение от dimon1984 Посмотреть сообщение
И обьясните плиз про синтаксис **
Тут по аналогии с простым указателем. Если указатель - это переменная, способная хранить адрес другой переменной, то указатель на указатель - это переменная, способная хранить адрес указателя.
Какая здесь связь с двумерным массивом? А вот какая. По сути двумерный массив можно представить как массив указателей, каждый из которых указывает на массив. Т.о. мы получаем массив, элементами которого являются объекты не числовых (или определённых пользователей) типов, а указатели. Отсюда имеем одну звезду в имени переменной. Но нам и сам этот массив указателей надо определить, он ведь тоже должен быть расположен где-то в памяти, и на него тоже что-то должно указывать. Отсюда имеем вторую звезду. Получаем, что (если имеем int **ptr; ) ptr указывает на область памяти, в которой могут лежать элементы типа int * (откинули первую звезду). И каждый из этих элементов указывает на область памяти, в которой могут лежать элементы типа int (откинули вторую звезду). Таким же образом можно представить массивы больших размерностей.

Добавлено через 4 минуты
Цитата Сообщение от dimon1984 Посмотреть сообщение
и что значит такой синтаксис? *(*...)
Уточните. Он много что может значить, в зависимости от контекста. Какой конкретно вариант вас интересует?
dimon1984
40 / 38 / 0
Регистрация: 22.01.2011
Сообщений: 670
02.03.2011, 01:42  [ТС]     Указатели :) #3
*(*...)
к примеру массив указателей типа int* - называется ptr. Допустим ptr[x][y]
*(*(ptr+x)+y).
Благодарю. Пока что вникаю в ответ
C++
1
2
char m[2][6] = {"hello", "world"};
char (*ptr)[6] = m;
вторая строка пока что не очень понятна Допустим почему нельзя звёздочку ставить за скобкой *(ptr)[6] = m; ?
Обьясните пожалуйста, ведь я потому и обратился, чтобы обьяснили желательно на пальцах по дружески По книгам сложно понять.
И на простых примерах, можно даже с ассемб-ми вставками.
kazak
 Аватар для kazak
3030 / 2351 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
02.03.2011, 06:57     Указатели :) #4
silent_1991, а этот пример с указателем на массив из шести элементов вообще работает?

dimon1984, назначить указатель на двумерный массив можно к примеру так
C++
1
2
3
4
int mas[3][3];
int *pMas =(int*)mas;
//обращение к элементу
pMas[i*j+j]; //i-строка, j-столбец
dimon1984
40 / 38 / 0
Регистрация: 22.01.2011
Сообщений: 670
02.03.2011, 13:10  [ТС]     Указатели :) #5
тот пример работает:
C++
1
2
3
char m[2][6] = {"hello", "world"};
char (*ptr)[6] = m;
cout<<*ptr<<' '<<m[1]<<endl;
кстати возник опять вопрос
C++
1
2
3
char m[2][6] = {"hello", "world"}
char *pMas =(char*)m;
cout<<pMas<<' '<<m[1]<<endl;
почему в первом случае в 3-й строчке нужна *(звёзд-ка), а во втором нет? Оба примера работают.
И ответьте пожалуйста на этот вопрос. Нашёл просто пример для вникания
допустим есть массив:
C++
1
2
3
4
5
  char week [ DAYS ][ MAX ] =
  {
    "Понедельник", "Вторник", "Среда", "Четверг",
    "Пятница", "Суббота", "Воскресенье"
  };
как к примеру с помощью указателей отсортировать массив? Я знаю что указатель это отдельная переменная(4 байта), которая хранит адрес.
но как поиграться с ними при сортировке week ?

Добавлено через 1 час 18 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//  char m[2][6] = {"hello", "world"};
//  char m[]="hello";
//  char m='h';
//  int m[2][3]={{1,2,3},{4,5,6}};
    int m=5;
    int* p;
    _asm
    {
//      xor eax,eax
//      mov ah,m
        mov eax,dword ptr m
        mov p,eax
    }
    cout<<*p<<endl;
Ещё вопрос: почему этот код компилируется, но выдаёт ошибку при запуске?

Добавлено через 43 минуты
C++
1
2
3
int x = 5;
int* p = &x;
int &s = x;
Наверно проще будет это понять так это увидеть это изнутри.
Напишите плиз ассемб-ю вставку, эквивалентную верхним трём строчкам
Жду с нетерпением ответа на любой вопрос
silent_1991
Эксперт C++
4949 / 3025 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
02.03.2011, 13:25     Указатели :) #6
Цитата Сообщение от kazak Посмотреть сообщение
а этот пример с указателем на массив из шести элементов вообще работает?
А вы как думаете?

Цитата Сообщение от dimon1984 Посмотреть сообщение
*(*(ptr+x)+y)
Здесь конструкция такая:
Когда мы прибавляем к указателю целое число, на самом деле происходит смещение указателя на это самое число ячеек заданного типа (именно поэтому надо указывать тип указателя - чтобы при индексации происходило смещение на правильное число байтов). Таким образом, ptr + x - смещение от начала массива ptr на x ячеек памяти. Теперь нам надо получить значение этой ячейки, поэтому мы к этому выражению применяем операцию разыменования - *(ptr + x). Поскольку значением ячейки является указатель (массив двумерный), то к полученному значению снова можно применить ту же операцию. Т.е. на самом деле теперь *(ptr + x) - тоже адрес. Тогда *(ptr + x) + y - уже смещение относительно строки ptr + x на y ячеек по столбцам. Но нас интересует конкретное значение в заданной ячейке, поэтому мы снова применяем операцию разыменования - *(*(ptr + x) + y) - и получаем элемент заданного типа (например int).

Цитата Сообщение от dimon1984 Посмотреть сообщение
почему нельзя звёздочку ставить за скобкой *(ptr)[6] = m;
Потому что когда компилятор разбирает такое выражение, он сначала смотрит направо, потом налево. Таким образом при разборе выражения char *(ptr)[6] он будет строить такую картину. ptr - это (смотрит направо - скобка, смотрит налево - скобка, смотрит направо - видит [6]) массив из шести (смотрит налево - видит char *) указателей на char. А мы добивались другого. При разборе конструкции char (*ptr)[6] получаем ptr - это (смотрим направо - скобка, смотрим налево - *) указатель на (смотрим направо - видим [6]) массив из шести (смотрим налево - видим char) элементов типа char, чего мы и хотели добиться.
Escapable
54 / 54 / 1
Регистрация: 09.11.2010
Сообщений: 120
02.03.2011, 13:39     Указатели :) #7
Цитата Сообщение от dimon1984 Посмотреть сообщение

Добавлено через 1 час 18 минут
C++
1
2
3
4
    int m=5;
    int* p;
    
    cout<<*p<<endl;
Ещё вопрос: почему этот код компилируется, но выдаёт ошибку при запуске?
Ошибка, т.к. у вас указатель 'p' не инициализирован (не содержит адреса какой-либо переменной). А в третьей строке вы его еще и разыменовывать пробуете.
C++
1
2
3
4
int m=5;
int *p = &m;
cout<<*p<<endl; // теперь при разыменовании указателя 'p', на экран будет выведено значение содержащееся в нем (т.е. 5)
cout<<p<<endl; // теперь будет выведен адрес указателя 'p' (в данном примере он будет равен адресу переменной 'm')
dimon1984
40 / 38 / 0
Регистрация: 22.01.2011
Сообщений: 670
02.03.2011, 13:44  [ТС]     Указатели :) #8
'p' не инициализирован
так в _asm{} p инициализирован ведь
Escapable
54 / 54 / 1
Регистрация: 09.11.2010
Сообщений: 120
02.03.2011, 13:47     Указатели :) #9
dimon1984, к сожалению в ассемблере "не секу".
kazak
 Аватар для kazak
3030 / 2351 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
02.03.2011, 14:15     Указатели :) #10
Цитата Сообщение от silent_1991 Посмотреть сообщение
А вы как думаете?
Уже не думаю, уже понял) Но раньше я такой записи не встречал.

Цитата Сообщение от dimon1984 Посмотреть сообщение
почему в первом случае в 3-й строчке нужна *(звёзд-ка), а во втором нет? Оба примера работают.
В данном случае pMas обычный указатель на char, для которого cout перегружен таким образом, что елси cout получает имя указателя, он выводит содержимаое памяти на экран начиная с символа на который указывает указатель до тех пор, пока не встретит нулевой символ. А ptr является некоторым аналогом двумерного массива и с который работает как двумерный массив.

Цитата Сообщение от dimon1984 Посмотреть сообщение
как к примеру с помощью указателей отсортировать массив?
Учти, что в твоем примере объявлен массив константных строк, в котором не возможно будет поменять значения сторок и непосредственно сам массив отсортировать не получится. Сдесь можно объявить массив указателей, в каждый указатель которого записывается адрес отдельной строки исходного массива и отсортировать этот массив указателей как тебе требуется.

Цитата Сообщение от dimon1984 Посмотреть сообщение
Ещё вопрос: почему этот код компилируется, но выдаёт ошибку при запуске?
Цитата Сообщение от dimon1984 Посмотреть сообщение
int m=5;
C++
1
2
3
4
5
6
7
8
9
10
 int* p;
 _asm
 {
// xor eax,eax
// mov ah,m
 mov eax,dword ptr m // [U]записать содержимое m в eax[/U], m = 5
 mov p,eax // записать содержимое eax в p, поле этого p будет равняться 5!
 }
 cout<<*p<<endl;//получить содержимое находящееся по адресу p, т.е. 5, а по младшим адрессам 
обычно запрещенно чтение\запись
Правильно будет вместо mov eax,dword ptr m написать lea eax,dword ptr m
dimon1984
40 / 38 / 0
Регистрация: 22.01.2011
Сообщений: 670
02.03.2011, 15:53  [ТС]     Указатели :) #11
lea eax,dword ptr m
правильней будет lea eax, m
немного вспомнил .Ещё есть offset (mov eax, offset m) но почему то не работает - ошибка
объявлен массив константных строк, в котором не возможно будет поменять значения сторок и непосредственно сам массив отсортировать не получится
про это я догадывался А можно пример, как отсортировать с помощью указателей, до того момента, пока я сам не придумал. Хотелось бы посмотреть на правильный пример

Добавлено через 1 час 15 минут
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
int main ( )
{
    const int DAYS =7; 
    void bsort(char**,int); //прототип 
    //массив указателей на char 
    char*arrptrs [DAYS] = {"Sunday ","Monday" ,"Tuesday","Wednesday",\
        "Thursday","Friday ","Saturday " };
 
    cout <<"Neuporyado4eniy : "<<endl; 
    for(int j=0;j<DAYS;j++) //вывести неупорядоченные 
    //строки 
    cout <<*(arrptrs+j)<<endl; 
    bsort(arrptrs,DAYS); //сортировать строки 
 
    cout <<"\nuporyado4eniy: "<<endl; 
    for(j=0;j<DAYS;j++) //вывести сортированные строки 
    cout <<*(arrptrs+j)<<endl; 
 
 
    system("pause");
    return 0;
}
 
void bsort(char**pp,int n) //сортировать указатели на строки 
{ 
    void order(char**,char**); //прототип 
    int j,k; //индексы массива 
    for(j=0;j<n-1;j++) //внешний цикл 
        for(k=j+1;k<n;k++) //внутренний цикл 
            order(pp+j,pp+k); //упорядочить содержимое 
// указателей 
}
void order(char**pp1,char**pp2) //сортирует два указателя 
{ //если в первом строка больше 
    if(strcmp(*pp1,*pp2)>0) //чем во втором 
    { 
        char*tempptr =*pp1; //обменять указатели 
        *pp1 = *pp2;
        *pp2 = tempptr;
    }
}
Нашёл решение ,и есть вопросы
C++
1
2
    char*arrptrs [DAYS] = {"Sunday ","Monday" ,"Tuesday","Wednesday",\
        "Thursday","Friday ","Saturday " };
arrptrs - указатель. Как этот arrptrs связан с [DAYS]? arrptrs++ нельзя так делать. Почему?
и в функцию передаётся указатель науказатель void order(char**pp1,char**pp2)
потом идёт if(strcmp(*pp1,*pp2)>0) (одна звёздочка)
Похожий ответ давали правда, думаю со временем пойму на разнообразных примерах.
silent_1991
Эксперт C++
4949 / 3025 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
02.03.2011, 15:57     Указатели :) #12
arrptrs (вспоминаем правило право-лево) - это массив из days указателей на char. arrptrs++ сделать нельзя, потому что arrptrs - константный указатель. Зато можно сделать, например, *((arrptrs + 2) + 3), получим символ 's'.
dimon1984
40 / 38 / 0
Регистрация: 22.01.2011
Сообщений: 670
03.03.2011, 16:14  [ТС]     Указатели :) #13
Ну это вообще. Чуть голову не сломал. Все выражения идентичны:
C++
1
2
3
4
5
m[2][3];
*(m[2]+3);
(*(m+2))[3];
3[m[2]];
3[2[m]];
Почему эти записи синтаксически нормальны?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.03.2011, 17:45     Указатели :)
Еще ссылки по теме:

Указатели в С C++
Указатели C++
C++ Указатели
C++ Указатели
Указатели C++

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

Или воспользуйтесь поиском по форуму:
silent_1991
Эксперт C++
4949 / 3025 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
03.03.2011, 17:45     Указатели :) #14
m[2][3]: это понятно
*(m[2] + 3): m[2] здесь - это указатель, третий по счёту в массиве указателей m. Прибавив к нему 3, мы сместимся в массиве, на который указывает этот указатель, на 3 элемента, а после разыменования получим значение элемента m[2][3]
(*(m + 2))[3]: аналогично предыдущему, только тут мы смещаемся сначала в массиве указателей, а потом применяем явную индексацию с помощью [].
3[m[2]]: конструкцию ptr[index] компилятор разворачивает в конструкцию *(ptr + index). А, значит, конструкцию index[ptr] компилятор развернёт в *(index + ptr), что эквивалентно первому. Если m[2][3] - это *(*(m + 2) + 3), то 3[m[2]] - это *(3 + *(m + 2)), что эквивалентно первому варианту.
3[2[m]]: аналогично, получим конструкцию *(3 + *(2 + m)), что аналогично *(*(m + 2) + 3).
Yandex
Объявления
03.03.2011, 17:45     Указатели :)
Ответ Создать тему
Опции темы

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