Re: Кое-что туточнить у знатоков.
От: rg45 СССР  
Дата: 11.08.11 18:16
Оценка: 84 (11) +3
Здравствуйте, LaptevVV, Вы писали:

LVV>Как читается данное объявление.

LVV>
LVV>const int N = 10;
LVV>int M = 5;
LVV>unsigned char (*p)[N] = new unsigned char[M][N];
LVV>

LVV>Указатель на массив из N элементов, каждый из которых является массивом из 5 элементов.
LVV>Это правильно?
LVV>Далее: тип выражения при разыменовании *p будет массив из 5 элементов. Или как-то иначе? []

По этому поводу есть один замечательный тост упражнение: написать щаблон функции, принимающей выражения, имеющие тип любой сложности и возвращающей строковое представление этого типа.

Вспомнив про rtti и typeid, выполнить задание, казалось бы, не сложно:
template<typename T> struct TypeReader { static std::string read() { return typeid(T).name(); } };
template<typename T> std::string read_type(T&) { return TypeReader<T>::read(); }
template<typename T> std::string read_type(const T&) { return TypeReader<const T>::read(); }
template<typename T> std::string read_type(volatile T&) { return TypeReader<volatile T>::read(); }
template<typename T> std::string read_type(const volatile T&) { return TypeReader<const volatile T>::read(); }


Только вот если мы на вход read_type подадим что-то типа такого:
std::cout << read_type<int(*(&)[42])()>() << std::endl;

То получим в ответ что-то типа такого:
int (__cdecl*[42])(void)

Вряд ли это то, чего мы хотели. Но тут мы вспоминаем про специализации (иногда частичные):
template<typename T> struct TypeReader<volatile T> { static std::string read() { return "Volatile " + TypeReader<T>::read(); } };
template<typename T> struct TypeReader<const T> { static std::string read() { return "Constant of " + TypeReader<T>::read(); } };
template<typename T> struct TypeReader<const volatile T> { static std::string read() { return "Constant Volatile of " + TypeReader<T>::read(); } };
template<typename T> struct TypeReader<T&> { static std::string read() { return "Reference to " + TypeReader<T>::read(); } };
template<typename T> struct TypeReader<T*> { static std::string read() { return "Pointer(s) to " + TypeReader<T>::read(); } };
template<typename T> struct TypeReader<T()> { static std::string read() { return "Function returning " + TypeReader<T>::read(); } };
template<typename T, int N> struct TypeReader<T[N]> { static std::string read() { return "Array of " + to_string(N) + " "+ TypeReader<T>::read(); } };

И, о чудо, в ответ на предыдущую строчку мы получаем (msvc-2008):
Reference to Array of 42 Pointer(s) to Function returning int

А теперь, перейдем к исходному примеру. Итак, дано:
const int N = 10;
int M = 5;
unsigned char (*p)[N] = new unsigned char[M][N];

Выражения:
std::cout << read_type(p) << std::endl;
std::cout << read_type(*p) << std::endl;

Дают нам соответственно:
Pointer(s) to Array of 10 unsigned char

и
Array of 10 unsigned char

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

Разумеется, я привел далеко не полный список возможных специализаций, из можно расширять до бесконесности: функции принимающие различное количество параметров, различные протоколы вызова, члены классов и пр. др. ИМХО, весьма полезное упражнение для изучающих C++.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re: Кое-что туточнить у знатоков.
От: vitabrevis  
Дата: 09.08.11 15:22
Оценка: 41 (6)
Здравствуйте, LaptevVV, Вы писали:

LVV>Как читается данное объявление.

LVV>
LVV>const int N = 10;
LVV>int M = 5;
LVV>unsigned char (*p)[N] = new unsigned char[M][N];
LVV>

LVV>Указатель на массив из N элементов, каждый из которых является массивом из 5 элементов.
LVV>Это правильно?
LVV>Далее: тип выражения при разыменовании *p будет массив из 5 элементов. Или как-то иначе?
Как правильно читать объявления
Re[3]: Кое-что туточнить у знатоков.
От: rg45 СССР  
Дата: 13.08.11 05:13
Оценка: +3
Здравствуйте, trophim, Вы писали:

T>Это все конечно хорошо. И изучить стоит лишь потому, что ну вот такие уж конструкции в языке существуют...

T>Но намеренно самому такое написать. Да это ж взрыв мозга. Более вырвиглазные конструкции можно придумать разве что на перле или брэйнфаке.

T>P.S. На код-ревью нужно подавать 220В к сидушке тому кто такое написал.


Без этих трудностей, которые мы (люди) сами себе создаем, а потом совершенствуем свое мастерство, преодолевая их, жизнь была бы скучна и бесцветна. И моего чудного упражнения не было бы.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re: Кое-что туточнить у знатоков.
От: breee breee  
Дата: 09.08.11 15:28
Оценка: +2
Здравствуйте, LaptevVV, Вы писали:

LVV>Как читается данное объявление.

LVV>
LVV>const int N = 10;
LVV>int M = 5;
LVV>unsigned char (*p)[N] = new unsigned char[M][N];
LVV>

LVV>Указатель на массив из N элементов, каждый из которых является массивом из 5 элементов.
LVV>Это правильно?
Наоборот. Указатель на (динамический) массив (или его первый элемент) из M=5 элементов, каждый из которых является (статическим) массивом из N=10 элементов.

А вообще, тут надо определится, что вы хотите прочитать — статический тип или описать представление массива в памяти. Статический тип p является "указатель на массив из N=10 элементов", а представление в памяти — выше.

LVV>Далее: тип выражения при разыменовании *p будет массив из 5 элементов. Или как-то иначе?

Из 10-ти.
Re: Кое-что туточнить у знатоков.
От: баг  
Дата: 11.08.11 07:24
Оценка: 22 (1)
Здравствуйте, LaptevVV, Вы писали:

unsigned char (*p)[N]
Re[3]: Кое-что туточнить у знатоков.
От: B0FEE664  
Дата: 10.08.11 10:24
Оценка: 1 (1)
Здравствуйте, vitabrevis, Вы писали:
V>Здравствуйте, trophim, Вы писали:

T>>Не по теме, но молчать сил нету: именно за такие конструкции убил бы Ритчи и Томпсона. Это ж надо было такие конструкции родить... А уж указатели на функции...

V>А чем Вам, позвольте спросить, указатели на функции не угодили? Очень удобная, иногда незаменимая конструкция...

Лично мне не нравится то, что имя указателя при декларации находится внутри описания типа.
Для функции:
int f(char c) { return 0; }

Вместо:
int(*)(char) pf = f;

приходится писать:
int(*pf)(char) = f;
И каждый день — без права на ошибку...
Re[3]: Кое-что туточнить у знатоков.
От: rg45 СССР  
Дата: 12.08.11 21:09
Оценка: 1 (1)
Здравствуйте, igna, Вы писали:

I>
R>>Pointer(s) to Array of 10 unsigned char
I>


I>Наверное (s) после Pointer здесь все-таки лишнее. Имеется ввиду видимо следующее:


I>
I>Pointer to object(s) of type Array of 10 unsigned char
I>


(s) я добавил, когда нужно было составить 'Array of Pointer(s)'. Лучше ничего не придумалось. Можно, конечно, добавить отдельную специализацию для массива указателей, но из-за такой мелочи вносить избыточность и портить красоту натюрморта как-то не хотелось.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Кое-что туточнить у знатоков.
От: Vamp Россия  
Дата: 09.08.11 15:33
Оценка: +1
LVV>>unsigned char (*p)[N] = new unsigned char[M][N];

BB>Наоборот. Указатель на (динамический) массив (или его первый элемент) из M=5 элементов,

Обоснуешь? Я считаю, что это указатель на массив из N элементов. Почему ты считаешь, что это указатель на массив из M? Где в типе p вообще M?
Да здравствует мыло душистое и веревка пушистая.
Re[2]: Кое-что туточнить у знатоков.
От: Vamp Россия  
Дата: 09.08.11 15:34
Оценка: +1
LVV>>Далее: тип выражения при разыменовании *p будет массив из 5 элементов. Или как-то иначе?
V>Да.
Здесь я, конечно, наврал — не посмотрел, чему равен N. Тип *p — массив из N элементов, а N равно 10.
Да здравствует мыло душистое и веревка пушистая.
Re: Кое-что туточнить у знатоков.
От: trophim Россия  
Дата: 09.08.11 20:37
Оценка: +1
Не по теме, но молчать сил нету: именно за такие конструкции убил бы Ритчи и Томпсона. Это ж надо было такие конструкции родить... А уж указатели на функции...
... << RSDN@Home 1.2.0 alpha 5 rev. 1495>>
Let it be! — Давайте есть пчелу!
Re[2]: Указатель на массив != указатель на первый элемент
От: igna Россия  
Дата: 11.08.11 07:13
Оценка: +1
Здравствуйте, breee breee, Вы писали:

BB>Указатель на (динамический) массив (или его первый элемент) ...


Указатель на массив это не то же самое, что указатель на первый элемент этого массива.

int a[2]; // Массив
int (*pa)[2] = &a; // Указатель на массив
int *pa0 = a; // Указатель на первый элемент массива


Понятия "указатель на динамический массив" не существует.

Термин "указатель на (динамический) массив" нередко используют вместо термина "указатель на первый элемент (динамического) массива", но на мой взгляд этого следует избегать даже в разговорной речи.
Re[5]: Кое-что туточнить у знатоков.
От: B0FEE664  
Дата: 12.08.11 09:42
Оценка: +1
Здравствуйте, vitabrevis, Вы писали:

BFE>>Лично мне не нравится то, что имя указателя при декларации находится внутри описания типа.

V>а typedef не поможет?

Да, поможет спрятать проблему в сам typedef, но ведь иногда и typedef'ы приходится читать:

typedef boost::units::quantity<boost::units::si::scaled::millisecond_unit, int>(*Func)(ValidCameraIndexEnum eSide, int nImageWidthInPixels, int nImageHeightInPixels, boost::units::quantity<boost::units::si::frequency, float> fImagesPerSecond, bool bInterlaced, BitsPerColorComponentEnum eBitsPerColor, ColorConversionEnumEx eColorEncodingMethod);


или вот другое следствие:

S v(S());
Автор: nen777w
Дата: 07.03.10
И каждый день — без права на ошибку...
Re[4]: Кое-что туточнить у знатоков.
От: trophim Россия  
Дата: 13.08.11 09:15
Оценка: :)
Долой немерле!
... << RSDN@Home 1.2.0 alpha 5 rev. 1495>>
Let it be! — Давайте есть пчелу!
Кое-что туточнить у знатоков.
От: LaptevVV Россия  
Дата: 09.08.11 15:14
Оценка:
Как читается данное объявление.
const int N = 10;
int M = 5;
unsigned char (*p)[N] = new unsigned char[M][N];

Указатель на массив из N элементов, каждый из которых является массивом из 5 элементов.
Это правильно?
Далее: тип выражения при разыменовании *p будет массив из 5 элементов. Или как-то иначе?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Кое-что туточнить у знатоков.
От: Vamp Россия  
Дата: 09.08.11 15:20
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Как читается данное объявление.

LVV>
LVV>const int N = 10;
LVV>int M = 5;
LVV>unsigned char (*p)[N] = new unsigned char[M][N];
LVV>

Тип p — указатель на массив размерностью N, состоящий из беззнаковых char, если ты об этом.


LVV>Далее: тип выражения при разыменовании *p будет массив из 5 элементов. Или как-то иначе?

Да.
Да здравствует мыло душистое и веревка пушистая.
Re[2]: Кое-что туточнить у знатоков.
От: LaptevVV Россия  
Дата: 09.08.11 15:25
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Здравствуйте, LaptevVV, Вы писали:


LVV>>Как читается данное объявление.

LVV>>
LVV>>const int N = 10;
LVV>>int M = 5;
LVV>>unsigned char (*p)[N] = new unsigned char[M][N];
LVV>>

V>Тип p — указатель на массив размерностью N, состоящий из беззнаковых char, если ты об этом.
Состоящий из массивов беззнаковых целых... Или массивов здесь опускаем?

LVV>>Далее: тип выражения при разыменовании *p будет массив из 5 элементов. Или как-то иначе?

V>Да.
Что это нам дает? Этому указателю без преобразования типа можно присвоить только либо другой указатель того же типа, либо адрес массива из 5 элементов char... Лан, понятно.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[3]: Кое-что туточнить у знатоков.
От: Vamp Россия  
Дата: 09.08.11 15:29
Оценка:
LVV>>>Как читается данное объявление.
LVV>>>
LVV>>>const int N = 10;
LVV>>>int M = 5;
LVV>>>unsigned char (*p)[N] = new unsigned char[M][N];
LVV>>>

V>>Тип p — указатель на массив размерностью N, состоящий из беззнаковых char, если ты об этом.
LVV>Состоящий из массивов беззнаковых целых... Или массивов здесь опускаем?
Нет, это указатель на массив, состоящий из чаров (а не целых). В данном определении один массив (а не два) и один указатель.

LVV>>>Далее: тип выражения при разыменовании *p будет массив из 5 элементов. Или как-то иначе?

LVV>Что это нам дает?
"А куда бы ты хотела попасть?" (С) Алиса в Стране Чудес.
Да здравствует мыло душистое и веревка пушистая.
Re[3]: Кое-что туточнить у знатоков.
От: breee breee  
Дата: 09.08.11 15:44
Оценка:
Здравствуйте, Vamp, Вы писали:

LVV>>>unsigned char (*p)[N] = new unsigned char[M][N];


BB>>Наоборот. Указатель на (динамический) массив (или его первый элемент) из M=5 элементов,

V>Обоснуешь? Я считаю, что это указатель на массив из N элементов. Почему ты считаешь, что это указатель на массив из M?
Это зависит от того, о чем мы говорим. Если о статическом типе p, то да, указатель на массив из N элементов.
Если о том, на что с точки зрения программиста указывает указатель p, то это указатель на динамический массив из M элементов.
Ведь работать он с ним будет именно так:
for (int i = 0 ; i < M ; ++i)
for (int j = 0 ; j < N ; ++j)
    p[i][j] = ...;


V>Где в типе p вообще M?

ТС спросил "Как читается данное объявление", а не "как читается тип переменной p". Все зависит от того, что на самом деле имелось в виду.
Re[4]: Кое-что туточнить у знатоков.
От: Vamp Россия  
Дата: 09.08.11 16:11
Оценка:
BB>>>Наоборот. Указатель на (динамический) массив (или его первый элемент) из M=5 элементов,
V>>Обоснуешь? Я считаю, что это указатель на массив из N элементов. Почему ты считаешь, что это указатель на массив из M?
BB>Это зависит от того, о чем мы говорим. Если о статическом типе p, то да, указатель на массив из N элементов.

То есть все-таки указатель на массив из N элементов, о чем бы мы не говорили.


BB>Если о том, на что с точки зрения программиста указывает указатель p, то это указатель на динамический массив из M элементов.

Нет, это указатель на статический массив из N элементов, и "работать" он будет именно так, как работает указатель на статический массив.

BB>Ведь работать он с ним будет именно так:

BB>
BB>for (int i = 0 ; i < M ; ++i)
BB>for (int j = 0 ; j < N ; ++j)
BB>    p[i][j] = ...;
BB>


Ну да, арифметику указателей никто отменял.

BB>ТС спросил "Как читается данное объявление", а не "как читается тип переменной p". Все зависит от того, что на самом деле имелось в виду.

На мой взгляд, все предельно четко и конкретно.
Да здравствует мыло душистое и веревка пушистая.
Re[2]: Кое-что туточнить у знатоков.
От: vitabrevis  
Дата: 10.08.11 04:10
Оценка:
Здравствуйте, trophim, Вы писали:

T>Не по теме, но молчать сил нету: именно за такие конструкции убил бы Ритчи и Томпсона. Это ж надо было такие конструкции родить... А уж указатели на функции...

А чем Вам, позвольте спросить, указатели на функции не угодили? Очень удобная, иногда незаменимая конструкция...
Re[3]: Указатель на массив != указатель на первый элемент
От: breee breee  
Дата: 11.08.11 07:27
Оценка:
Здравствуйте, igna, Вы писали:

I>Здравствуйте, breee breee, Вы писали:


BB>>Указатель на (динамический) массив (или его первый элемент) ...


I>Указатель на массив это не то же самое, что указатель на первый элемент этого массива.


I>
I>int a[2]; // Массив
I>int (*pa)[2] = &a; // Указатель на массив
I>int *pa0 = a; // Указатель на первый элемент массива
I>


Я говорил про динамический массив.

I>Понятия "указатель на динамический массив" не существует.

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

I>Термин "указатель на (динамический) массив" нередко используют вместо термина "указатель на первый элемент (динамического) массива", но на мой взгляд этого следует избегать даже в разговорной речи.


Не вижу криминала.
Re[4]: Указатель на массив != указатель на первый элемент
От: igna Россия  
Дата: 11.08.11 09:10
Оценка:
Здравствуйте, breee breee, Вы писали:

BB>Не вижу криминала.


Тем не менее криминал есть, поскольку термин "указатель на массив" становится двусмысленным, означая с одной стороны то же что и "указатель на первый элемент массива", с другой стороны собственно "указатель на массив".
Re[4]: Кое-что туточнить у знатоков.
От: vitabrevis  
Дата: 11.08.11 19:34
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Лично мне не нравится то, что имя указателя при декларации находится внутри описания типа.

BFE>Для функции:
BFE>
BFE>int f(char c) { return 0; }
BFE>

BFE>Вместо:
BFE>
BFE>int(*)(char) pf = f;
BFE>

BFE>приходится писать:
BFE>
BFE>int(*pf)(char) = f;
BFE>

а typedef не поможет?
Re[2]: Кое-что туточнить у знатоков.
От: igna Россия  
Дата: 12.08.11 06:46
Оценка:
Здравствуйте, rg45, Вы писали:

R>Pointer(s) to Array of 10 unsigned char


Наверное (s) после Pointer здесь все-таки лишнее. Имеется ввиду видимо следующее:

Pointer to object(s) of type Array of 10 unsigned char


Но и такое означает введение нового понятия "указателя на объекты" в дополнение к имеющемуся "указателю на объект", а оно действительно надо?
Re[2]: Кое-что туточнить у знатоков.
От: trophim Россия  
Дата: 12.08.11 08:13
Оценка:
Это все конечно хорошо. И изучить стоит лишь потому, что ну вот такие уж конструкции в языке существуют...
Но намеренно самому такое написать. Да это ж взрыв мозга. Более вырвиглазные конструкции можно придумать разве что на перле или брэйнфаке.

P.S. На код-ревью нужно подавать 220В к сидушке тому кто такое написал.
Let it be! — Давайте есть пчелу!
Re[3]: Кое-что туточнить у знатоков.
От: LaptevVV Россия  
Дата: 12.08.11 08:18
Оценка:
Здравствуйте, trophim, Вы писали:

T>Это все конечно хорошо. И изучить стоит лишь потому, что ну вот такие уж конструкции в языке существуют...

T>Но намеренно самому такое написать. Да это ж взрыв мозга. Более вырвиглазные конструкции можно придумать разве что на перле или брэйнфаке.

T>P.S. На код-ревью нужно подавать 220В к сидушке тому кто такое написал.

Сам я никогда записью
type (*p)[size]

не пользовался. Поэтому и не возникало вопросов.
А последние несколько лет вообще пользуюсь исключительно контейнерами STL, поэтому практически и забыл, чего не знал...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Кое-что туточнить у знатоков.
От: jyuyjiyuijyu  
Дата: 14.08.11 16:13
Оценка:
Здравствуйте, LaptevVV, Вы писали:

*LVV>const int N = 10;
LVV>int M = 5;
LVV>unsigned char (*p)[N] = new unsigned char[M][N];
LVV>


Тип p — указатель на массив размерностью N, состоящий из беззнаковых char, если ты об этом.


LVV>Далее: тип выражения при разыменовании *p будет массив из 5 элементов. Или как-то иначе?

Да.

всегда же было если int (*p)[2] то *p == указатель на первый элемент массива
тоесть если имеем указатель на массив то после разыменования имеем указатель на первый элемент
ну вот пример
int (*p)[2];
*(*(p + i) + j)
вот тут видно как указатель на массив превращается в указатель на первый элемент
а потом уж после второго разымнования в элемент
с чего вы взяли что typeof(*p) == массив а не указатель ?
Re[2]: Кое-что туточнить у знатоков.
От: rg45 СССР  
Дата: 15.08.11 08:32
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>*LVV>const int N = 10;

LVV>>int M = 5;
LVV>>unsigned char (*p)[N] = new unsigned char[M][N];
LVV>>

J>Тип p — указатель на массив размерностью N, состоящий из беззнаковых char, если ты об этом.


LVV>>Далее: тип выражения при разыменовании *p будет массив из 5 элементов. Или как-то иначе?

J>Да.

Только массив не из 5-ти элементов, а из 10-ти
--
Не можешь достичь желаемого — пожелай достигнутого.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.