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

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

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 64, средняя оценка - 4.86
Gepar
1175 / 531 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
#1

Указатель на массив char и прочее - C++

14.09.2011, 11:40. Просмотров 8398. Ответов 12
Метки нет (Все метки)

Страуструп для проверки прочитанного в заданиях после одной из глав просит через typedef сделать пару объявлений и вот как делать некоторые из них я что-то не понял, в частности:

Используйте typedef для определения типов:
- указатель на массив char
...
- массив из 7 указателей на int
- указатель на массив из 7 указателей на int
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.09.2011, 11:40     Указатель на массив char и прочее
Посмотрите здесь:
Указатель на массив char C++
C++ Символьный массив и указатель на char
Указатель на двумерный массив char С.Прата C++
Объяснить работу функции, возвращающей указатель на указатель на char C++
array char* to char* (значения массива указателей в один указатель) C++
Реализовать 3 функции, каждая из которых принимает указатель на массив и количество элементов и возвращает указатель на новый массив. C++
C++ Указатель char*
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
stdcout
53 / 53 / 2
Регистрация: 06.04.2011
Сообщений: 210
14.09.2011, 12:05     Указатель на массив char и прочее #2
Gepar, с
- указатель на массив char
этим пока не разобрался.
- массив из 7 указателей на int
- указатель на массив из 7 указателей на int
возможно, так?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
 
typedef int* ARR_PTR[7];
typedef ARR_PTR* PTR_TO_ARR_PTR;
 
int main()
{
    int i;
    int arr[7] = { 1, 2, 3, 4, 5, 6, 7 };
 
    ARR_PTR ptr_to_arr = { arr, arr + 1, arr + 2, arr + 3, arr + 4, arr + 5, arr + 6 };
    for (i = 0; i < 7; ++i)
        std::cout << *ptr_to_arr[i] << " ";
    std::cout << std::endl;
 
    PTR_TO_ARR_PTR p = &ptr_to_arr;
    for (i = 0; i < 7; ++i)
        std::cout << *(*p)[i] << " ";
}
kazak
3034 / 2355 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
14.09.2011, 12:21     Указатель на массив char и прочее #3
Цитата Сообщение от Gepar Посмотреть сообщение
- указатель на массив char
C++
1
typedef char **pArChar;
!?
silent_1991
Эксперт С++
4960 / 3036 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
14.09.2011, 12:41     Указатель на массив char и прочее #4
Цитата Сообщение от kazak Посмотреть сообщение
C++
1
typedef char **pArChar;
А мне почему-то подумалось
C++
1
typedef char * char_ptr_t;
kazak
3034 / 2355 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
14.09.2011, 12:49     Указатель на массив char и прочее #5
Цитата Сообщение от silent_1991 Посмотреть сообщение
typedef char * char_ptr_t;
Это же вроде просто указатель на чар.
nxnx
Формучанин
362 / 293 / 16
Регистрация: 02.11.2010
Сообщений: 1,234
14.09.2011, 12:53     Указатель на массив char и прочее #6
C++
1
typedef char(*pointer_to_mas)[];
не?
Evg
Эксперт CАвтор FAQ
17527 / 5765 / 368
Регистрация: 30.03.2009
Сообщений: 15,854
Записей в блоге: 26
14.09.2011, 13:17     Указатель на массив char и прочее #7
Цитата Сообщение от kazak Посмотреть сообщение
Это же вроде просто указатель на чар.
Указатель на char ничем не отличается от указателя на массив char'ов. Указателя на массив как такового типа в языке нет. Единственно, что при объявлении массива в качестве параметра вызова, он будет трактоваться как указатель

Цитата Сообщение от nxnx Посмотреть сообщение
C++
1
typedef char(*pointer_to_mas)[];
не?
Это есть массив, состоящий из указателей на char:

C
1
2
3
4
5
6
7
8
9
typedef int (*bbb)[6];
 
bbb b;
int *x;
 
void func (void)
{
  x = b[3];
}
Код
        movl    b, %eax
        addl    $72, %eax
        movl    %eax, x
Тут фактически в "x" записывается адрес "b" + 72 байта. 72 = 3 * 24, где 24 = 6 * 4, где 6 - количество элементов массива, а 4 - размер одного элемента массива (размер указателя). Хотя всё равно странная какая-то конструкция, типа выражения b[3] есть указатель. Надо посоображать, что же это означает

Добавлено через 2 минуты
Реально, это получается, что "bbb" есть указатель на массив из 6 int'ов (а не 6 указателей, как я написал выше)
kazak
3034 / 2355 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
14.09.2011, 13:28     Указатель на массив char и прочее #8
Evg, так что же это получается, типа в языке не предусмотренно, но реально его можно получить?
Evg
Эксперт CАвтор FAQ
17527 / 5765 / 368
Регистрация: 30.03.2009
Сообщений: 15,854
Записей в блоге: 26
14.09.2011, 14:03     Указатель на массив char и прочее #9
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от Evg Посмотреть сообщение
Тут фактически в "x" записывается адрес "b" + 72 байта
Гоню. Из b читается значение, к нему прибавляется 72 и результат записывается в "x". Потому как значение выражение b[3] номинально есть "массив из 6 элементов", а массив в правой части присваивания трактуется как адрес первого элемента. Это я просто поясняю, почему я изначально сделал неверный вывод - неправильно трактовал то, что написано в ассемблерном коде

Добавлено через 7 минут
Цитата Сообщение от kazak Посмотреть сообщение
Evg, так что же это получается, типа в языке не предусмотренно, но реально его можно получить?
Просто я не знаю, как это нормально словами объяснить. Просто "массив" и "массив из 6 элементов" - как бы разные вещи. Щас на примере попробую наваять

Добавлено через 19 минут
Я нагнал, когда писал "Указателя на массив как такового типа в языке нет". Имел в виду, что когда мы имеем указатель "int *p;", то с ним можно работать и как с указателем на скалярную переменную, обращаясь с ним типа "*p = 5;", и как с указателем на некую память, где лежит массив int'ов, и обращаться через "p[0] = 5; p[10] = 5;" и т.п. В этом отношении любая память, куда смотрит указатель, может трактоваться как массив, при этом нигде нет информации о том, какого размера этот массив. Да и вообще указатель может смотреть в середину массива:

C
1
2
3
4
int x[10];
int *p = &x[5];
p[-3] = 0; /* обращение в x[2]; */
p[2] = 0; /* обращение в x[7]; */
Когда через typedef вводится тип-массив, то это получается некая единая конструкция "массив из стольки-то элементов". Например, указатель на "массив из 6 int'ов" трактуется как указатель, смотрящий на массив, состоящий из 24-байтных элементов. И при индексации через такой указатель смещения будут работать в терминах 24-байтных элементов, а не в терминах 4-байтных элементов, как это происходило с указателем на int.

Понимаю, что объяснено сумбурно, но как-то затрудняюсь это внтяными словами пояснить

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
typedef int (arr6_t)[6];
 
void func (void)
{
  int arr6[6];
  int *ptr;
  arr6_t *arr6_ptr; /* указатель на массив */
 
  /* Просто имя массива в правой части трактуется как адрес первого
   * элемента массива, который фактически имеет тип int* */
  ptr = arr6;
 
  /* В правой части присваивания имеем r-выражение типа int* (см. выше),
   * а в левой - l-выражение типа "указатель на массив из 6 элементов".
   * Т.е. имеем присваивание между собой указателей разных типов, т.е.
   * конструкция некорректная. Хотя gcc, к примеру, такую конструкцию
   * съест, потому как он работает в своём расширении языка, а не в стандартном */
  arr6_ptr = arr6;
 
  /* R-выражение "&arr6" с точки зрения полученного кода ничем неотличается
   * от r-выражения "arr6", но "arr6" сточки зрения языка трактуется как
   * "&(arr6[0])" и имеет тип int*, а вот "&arr6" трактуется именно так,
   * как и написано (т.е. адрес на переменную, а не адрес на первый элемент),
   * и потому имеет тип "указатель на массив из 6 элементов" */
  arr6_ptr = &arr6;
}
В итоге "указатель на массив" в языке всё-таки есть, но вот с таким немного извращённым синтаксисом и непростым пониманием

Добавлено через 4 минуты
И ещё в догонку к коду:

C
1
2
3
4
5
6
7
8
9
10
  /* Исходя из предыдущих объяснений в правой части выражение имеет тип
   * "указатель на массив из 6 int'ов", а в левой - "указатель на int". Формально
   * такое присваивание не является корректным */
  ptr = &arr6;
 
  /* Тут всё корректно */
  ptr = &(arr6[0]);
 
  /* Тут некорректно */
  arr6_ptr = &(arr6[0]);
В итоге мы одно и тоже действие получили шестью способами. Все способы сгенерят один и тот же код (если кокнретное расширение языка это допускает). Но из-за трактовки языка, три из этих конструкций являются некорректными
nxnx
Формучанин
362 / 293 / 16
Регистрация: 02.11.2010
Сообщений: 1,234
14.09.2011, 16:16     Указатель на массив char и прочее #10
C
1
2
3
4
5
6
7
8
9
typedef int (*bbb)[];
 
bbb b;
int x;
 
void func (void)
{
  x = (*b)[3];
}
gcc -Wall -S :
Assembler
1
2
3
4
5
;...
    movl    b, %eax
    movl    12(%eax), %eax
    movl    %eax, x
;...
это ведь явно указатель на массив
Gepar
1175 / 531 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
14.09.2011, 16:34  [ТС]     Указатель на массив char и прочее #11
Цитата Сообщение от kazak Посмотреть сообщение
1 typedef char **pArChar;
!?
Это же указатель на указатель. Такой пункт тоже был отдельно.


Evg, возможно Вы и правы, я тоже в начале подумал что у нас определения отдельного в виде указателя на массив нет вот и реши спросить здесь, может я не знаю чего.
nxnx
Формучанин
362 / 293 / 16
Регистрация: 02.11.2010
Сообщений: 1,234
14.09.2011, 17:17     Указатель на массив char и прочее #12
Цитата Сообщение от Evg Посмотреть сообщение
C
1
2
3
4
5
6
7
8
9
typedef int (*bbb)[6];
 
bbb b;
int *x;
 
void func (void)
{
  x = b[3];
}
Код
        movl    b, %eax
        addl    $72, %eax
        movl    %eax, x
Тут фактически в "x" записывается адрес "b" + 72 байта. 72 = 3 * 24, где 24 = 6 * 4, где 6 - количество элементов массива, а 4 - размер одного элемента массива (размер указателя). Хотя всё равно странная какая-то конструкция, типа выражения b[3] есть указатель. Надо посоображать, что же это означает
я думаю так.
у нас b указатель. По адресу b расположен массив из 6 интов. тоесть он занимает 6*4 байт.
А если массив не один...
b[1] будет указывать на второй массив. Второй массив уже находится дальше, его смещение относительно первого адреса b есть 6*4
b[2] 6*4+6*4
b[3] 6*4+6*4+6*4=72.
b[3] есть указатель на четвёртый массив(который состоит из 6 интов)

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
typedef int (*bbb)[6];
 
bbb b;
int* x;
int* y;
int* y2;
int (*x2)[6]; 
void func (void)
{
//в комментариях под [3] я имею в виду индекс. У четвёртого массива индекс 3.
x = b[3];//указатель на [0] элемент [3] массива
 
y=&x[1];//указатель на [1] элемент массива, который находится по адресу x
y2=&(b[3])[1];//указатель на [1] элемент [3] массива
 
x2 = &b[3];//указатель на [3] массив 
}
чтобы было нагляднее надо включить оптимизацию gcc -Wall -O3 -S :
Assembler
1
2
3
4
5
6
7
    movl    b, %edx
    leal    72(%edx), %eax
    movl    %eax, x
    addl    $76, %edx
    movl    %edx, y
    movl    %edx, y2
    movl    %eax, x2
от сюда явно видно что указатели x и y равны между собой. причём y указывает на следующий элемент массива(его адрес на sizeof(int) больше)

Добавлено через 11 минут
о блин, прочёл 9 пост, получается я написал тоже самое, только другими словами
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.09.2011, 03:06     Указатель на массив char и прочее
Еще ссылки по теме:
Указатель char* C++
C++ Указатель на char
Указатель на char C++
Char указатель C++
Char и указатель на переменную C++

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

Или воспользуйтесь поиском по форуму:
accept
4821 / 3241 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
15.09.2011, 03:06     Указатель на массив char и прочее #13
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
 
int main(void)
{
    char a[2][4][6] = {
        { { "abcd" } },
        { { "efgh" } }
    };
    char (*pa)[4][6] = a;
    
    printf("%s\n", pa[0][0]);
    pa++;
    printf("%s\n", pa[0][0]);
    return 0;
}
Код
[guest@localhost tests]$ .ansi t.c -o t
[guest@localhost tests]$ ./t
abcd
efgh
[guest@localhost tests]$
Yandex
Объявления
15.09.2011, 03:06     Указатель на массив char и прочее
Ответ Создать тему
Опции темы

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