реклама на сайте
подробности

 
 
19 страниц V  « < 5 6 7 8 9 > »   
Reply to this topicStart new topic
> Си
igorle
сообщение Mar 2 2013, 14:51
Сообщение #91


Местный
***

Группа: Свой
Сообщений: 338
Регистрация: 14-07-12
Пользователь №: 72 753



Цитата(XVR @ Mar 2 2013, 18:39) *
Код
    int dim1=5;
    int dim2=10;

    int** my_array=GenerateArray(dim1,dim2);

    my_array[i][j] = ...


Забавно. Никогда так не делал. Первая реакция была - "ерунда". Потом подумал - а ведь должно работать....

Сообщение отредактировал igorle - Mar 2 2013, 14:56
Go to the top of the page
 
+Quote Post
XVR
сообщение Mar 2 2013, 19:43
Сообщение #92


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Цитата(igorle @ Mar 2 2013, 18:51) *
Забавно. Никогда так не делал. Первая реакция была - "ерунда".
Это один из классических способов реализаций многомерных динамических массивов (я бы даже сказал, что самый первый из классических)

Go to the top of the page
 
+Quote Post
Буратино
сообщение Mar 2 2013, 22:07
Сообщение #93


Профессионал
*****

Группа: Свой
Сообщений: 1 433
Регистрация: 27-10-08
Из: Украина, Киев
Пользователь №: 41 215



Да, оч. интересно! Правда не совсем ппонимаю, как освобождать память из под такого массивчика? sm.gif
Если указатель связанный с данными через "new" погибнет, потеряется - память "потечет"!?

Если я использую библиотечные функции, ну например "strcat" библиотеки cLib, прототип описан в string.h, выделить память для результирующей строки должен программист? о_О

Код
/*
* Copyright (C) 2002     Manuel Novoa III
* Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
*
* Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
*/

#include "_string.h"

#ifdef WANT_WIDE
# define Wstrcat wcscat
#else
# define Wstrcat strcat
#endif

Wchar *Wstrcat(Wchar * __restrict s1, register const Wchar * __restrict s2)
{
    register Wchar *s = s1;

    while (*s++);
    --s;
    while ((*s++ = *s2++) != 0);

    return s1;
}
libc_hidden_def(Wstrcat)


--------------------
Брак - это такой вид отношений, в которых один всегда прав, - а другой - муж.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Mar 3 2013, 07:16
Сообщение #94


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(Tahoe @ Mar 1 2013, 04:45) *
Дьявол в мелочах (с).
Вот именно™
Цитата(Tahoe @ Mar 1 2013, 04:45) *
Тот случай, когда пренебежение терминологией, привело к не верному выводу. А именно, "указатель" != "адрес". Имя массива - не "указатель" на первый элемент, а "адрес" первого элемента.
Имя массива — это имя массива. Оно имеет тип «массив вон-того» (в зависимости от объявления).
Почти во всех выражениях оно автоматически приводится к указателю на первый элемент.
Цитата(C99)
6.3 Conversions
...
6.3.2 Other operands
6.3.2.1 Lvalues, arrays, and function designators
...
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
igorle
сообщение Mar 3 2013, 07:22
Сообщение #95


Местный
***

Группа: Свой
Сообщений: 338
Регистрация: 14-07-12
Пользователь №: 72 753



Цитата(XVR @ Mar 2 2013, 23:43) *
Это один из классических способов реализаций многомерных динамических массивов (я бы даже сказал, что самый первый из классических)

Я считаю что хороший способ запутать (и запугать) новичка. Вы должны теперь объяснить, что my_array и your_array следующем примере:
Код
int** my_array=GenerateArray(6, 9);
int  your_array[6][9];

это две большие разницы. И вообще эти переменные - разного типа. Это неочевидно ученику.
Давайте спросил Буратино (задачу решить на листочке, не используя компилятор):
- какого типа your_array?
- что вернет sizeof(my_array) и sizeof(your_array)?
- можно ли сделать такое присвоение int **his_array = your_array; ?
Go to the top of the page
 
+Quote Post
ReAl
сообщение Mar 3 2013, 07:25
Сообщение #96


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(Буратино @ Mar 3 2013, 00:07) *
Да, оч. интересно! Правда не совсем ппонимаю, как освобождать память из под такого массивчика? sm.gif
«наоборотом». Сначала удалить по каждому из указателей из массива указателей, потом удалить по указателю на массив.

Такие массивы удобны тем, что каждая «строка» выделена отдельно и хранится отдельно. Можно менять месстами строки, перемещая только значения указателей, не трогая данные.

Например, было актуально во времена «640 килобайт»
При фильтрации изображений, скажем, окном 3х3, можно выделить место на две дополнительных строки, начать фильтрацию в них. При получении третьей (номер 2) строки выходного изображения первая строка (номер 0) входного изображения уже не нужна, результат можно помещать в неё, потом в нужное место переписать указатель. В итоге через какое-то время строки изображений в памяти разбросаны как попало, но все работает :-)


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
igorle
сообщение Mar 3 2013, 07:38
Сообщение #97


Местный
***

Группа: Свой
Сообщений: 338
Регистрация: 14-07-12
Пользователь №: 72 753



Цитата
Если я использую библиотечные функции, ну например "strcat" библиотеки cLib, прототип описан в string.h, выделить память для результирующей строки должен программист? о_О

Да, и узнать это из исходников - похвальный, но не самый простой путь. Лучше читать man pages
Кстати - многие функции еще и не проверяют корректность параметров. Например strcat(NULL, "basa"); просто покрошится.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Mar 3 2013, 08:13
Сообщение #98


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(igorle @ Mar 3 2013, 09:22) *
это две большие разницы. И вообще эти переменные - разного типа. Это неочевидно ученику.
Давайте спросил Буратино
Давайте сначала Вы объясните ученику, как при помощи записи вида int your_array[что-то-одно][что-то-другое]; создать массив неизвестного заранее размера с времением жизни, выходящим за рамки функции, в которой он создан.

Был вопрос «зачем такое может быть нужно». Дан ответ. Дальше ученик должен думать. Различия можно объяснять.

Цитата(igorle @ Mar 3 2013, 09:22) *
- что вернет sizeof(my_array) и sizeof(your_array)?

sizeof(my_array) вернёт в точности то же самое, что тут вернёт sizeof(your_array)
Код
int foo(int your_array[6][9])
{
    return sizeof(your_array);
}
и всё равно придётся объяснять, почему sizeof(your_array) в двух разных местах возвращает разные значения.


Кстати, я считаю, что запись foo(char *arr[]) гораздо хуже, чем foo(char **arr).
В итоге-то одно и то же, у функций одинаковый прототип, принимают pointer to pointer to char.
В режиме компиляции С++ должно быть одинаковое mangled-имя.
В первой записи arr по сути тот же char **, только этого не видно (пресловутому ученику) и этот arr невозможно сделать константным.
foo(char const * const arr[])
Вот тут аж дальние char — константные. Указатели на них, хранящиеся в массиве, на который указывает аргумент arr (в С ведь массивы не передаются как параметры, не правда ли?) — тоже константные. А сам аргумент - не константный, хоть плачь.

Код
int foo(char const * const arr[])
{
        int i = 0;
        while( *arr++) ++i; // Тут всё отлчино!
        return i;
}

int moo(char const * const * const arr)
{
        int i = 0;
        while(*arr++) ++i; // А вот тут компилятор говорит об ошибке
        return i;
}
всё, что имеем:
Цитата
arrn.c: In function ‘moo’:
arrn.c:11: error: increment of read-only location ‘arr’

А с первой функцией все нормально, компилятор молчит.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Tahoe
сообщение Mar 3 2013, 08:53
Сообщение #99


Местный
***

Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600



Цитата(ReAl @ Mar 3 2013, 11:16) *
Имя массива — это имя массива. Оно имеет тип «массив вон-того» (в зависимости от объявления).Почти во всех выражениях оно автоматически приводится к указателю на первый элемент.

Ещё раз. Указатель, это переменная, занимающая место в памяти. Под адрес же, память не выделяется. Что там происходит дальше, на что похоже, как оптимизируется и т.п. - дело десятое.

Не знаю как сейчас, а еще 3-4 года назад тот же IAR/ARM, на максимальной оптимизации, генерил совершенно разный код в одном и том же цикле, для Array[i] и *(pArray+i). Т.е. работал совершенно по-разному ( через указатель гораздо быстрее ). "Хотя казалось бы..." (с). Пришлось ручками ковырять libavcodec, на предмет переделки обращения a[] в *pa, потому что иначе SAM7S64 не успевал размотать два канала честного ADPCM.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Mar 3 2013, 09:56
Сообщение #100


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(Tahoe @ Mar 3 2013, 10:53) *
Ещё раз. Указатель, это переменная, занимающая место в памяти.
Ну хорошо.
«is converted to an expression with type ‘‘pointer to type’’»
приводится к выражению типа «указатель на»
Не к «переменной типа „указатель на”». А к выражению. Приводится, а не есть им.
Результат этого выражения может не сохраняться в памяти. Может сохраняться во временной переменной в регистре. Может в результате оптимизации сразу компилироваться в тело команды.
Но сначала имя массива приводится к указателю на. Везде, кроме & и sizeof.
Только в результате этого приведения выражения
Код
array[i]
и
Код
i[array]
эквивалентны.

Да, кстати. Возьмём char a, b;. Теперь возьмём выражение a+b.
Приянто говорить «перед сложением a и b приводятся к целому».
Вы и здесь будете говорить «Ещё раз. Целое это переменная, занимающая место в памяти.» ?
«Целое», «указатель на» — это типы. А не переменные этих типов.

Кстати, и «переменная типа „указатель на”» может не занимать место в памяти. И даже в регистре. После оптимизации, конечно.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
igorle
сообщение Mar 3 2013, 10:20
Сообщение #101


Местный
***

Группа: Свой
Сообщений: 338
Регистрация: 14-07-12
Пользователь №: 72 753



Друзья. Эта тема создана Буратиной для Буратино. Он изучает С. Но в результате ветка превратилась в спор о дистнинкциях между несколькими опытными профессионалами. Это то, чего я опасался - вместо обучения получается запугивание.

Давайте вернемся а TC. Если человек пришел с вопросом, то надо отвечать на его языке. Любое знание должно прорасти. И его надо оберегать на начальных периодах. А если начинать тригонометрию не с прямоугольных прямоугольников, а с тригонометрических функций комплексных переменных, то толку не будет.

То что очевидно опытному - не сразу понятно начинающему. Время нужно.

Кстати, никто не ответил ясно на мой вопрос. Повторю. Что будет напечатано на 32 битном процессоре (решить на листочке, без компилятора):
Код
int** my_array=GenerateArray(6, 9);
int  your_array[6][9];

printf("%z %z\n", sizeof(my_array), sizeof(your_array));


К вопросу о споре. Я понимаю обе стороны. Позиция ReAl мне ближе. Просто Буратино жалко. Он уже сбежал из своей ветки.
Go to the top of the page
 
+Quote Post
sasamy
сообщение Mar 3 2013, 10:22
Сообщение #102


Знающий
****

Группа: Участник
Сообщений: 783
Регистрация: 22-11-08
Пользователь №: 41 858



Цитата(igorle @ Mar 2 2013, 18:51) *
Забавно. Никогда так не делал. Первая реакция была - "ерунда".


Причем первая реакция была правильной sm.gif это не массив а мутант

Код
int** GenerateArray(int dim1, int dim2)
{
int** rv=new int*[dim1];
for(int i=0;i<dim1;++i)
  rv[i]=new int[dim2];
return rv;
}


Цитата
An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type.


и даже динамическим мутантом его назвать сложно - нужно еще специальную ф-цию написать чтобы изменить его размерность в динамике.
Go to the top of the page
 
+Quote Post
Tahoe
сообщение Mar 4 2013, 05:36
Сообщение #103


Местный
***

Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600



Цитата(ReAl @ Mar 3 2013, 13:56) *
Ну хорошо.
«is converted to an expression with type ‘‘pointer to type’’»
приводится к выражению типа «указатель на»
Не к «переменной типа „указатель на”». А к выражению. Приводится, а не есть им.

Ну хорошо. (с) Потому что:
Цитата(Tahoe @ Mar 3 2013, 12:53) *
Что там происходит дальше, на что похоже, как оптимизируется и т.п. - дело десятое.


И что бы стало совсем понятно, о чем речь, наглядная демонстрация, что "адрес" != "указатель":
Код
uint8_t    Array[8];
Array++;

на выходе получим:
Цитата
Error[Pe137]: expression must be a modifiable lvalue



Цитата(igorle @ Mar 3 2013, 14:20) *
Друзья. Эта тема создана Буратиной для Буратино. Он изучает С. Но в результате ветка превратилась в спор о дистнинкциях между несколькими опытными профессионалами. Это то, чего я опасался - вместо обучения получается запугивание.

Вот я как раз именно об этом. Да не обидится ReAl, но объяснять, это отдельное искусство. Знаю много грамотных спецов, однако, дай Б-г, если четверть из них в состоянии внятно объяснить то, чем сами отлично владеют.
Go to the top of the page
 
+Quote Post
sasamy
сообщение Mar 4 2013, 06:57
Сообщение #104


Знающий
****

Группа: Участник
Сообщений: 783
Регистрация: 22-11-08
Пользователь №: 41 858



Цитата(Tahoe @ Mar 4 2013, 09:36) *
И что бы стало совсем понятно, о чем речь, наглядная демонстрация, что "адрес" != "указатель":


это не совсем наглядно - с константным указателем тоже ничего хорошего не получим.
Цитата
A pointer type describes an object whose value provides a reference to an entity of the referenced type.


имя массива объектом не является, его можно использовать только в выражениях, в этом его отличие от указателя.

Go to the top of the page
 
+Quote Post
Tahoe
сообщение Mar 4 2013, 08:22
Сообщение #105


Местный
***

Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600



Цитата(sasamy @ Mar 4 2013, 10:57) *
это не совсем наглядно - с константным указателем тоже ничего хорошего не получим.

"И о чем нам это должно говорить?" (с) Константный указатель, это по-прежнему указатель, даже если мы сознательно запретили его изменять.
Собсно, зачем я буду пересказывать классиков своими словами... K&R - Язык C - 5.3. Указатели и массивы.


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


UPD
На данном этапе, новичку надо не про оптимизации рассказывать, а вбить в голову простую мысль, что адрес и указатель, вещи тесно связанные, но это не одно и то же!
Go to the top of the page
 
+Quote Post

19 страниц V  « < 5 6 7 8 9 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 22:37
Рейтинг@Mail.ru


Страница сгенерированна за 0.0153 секунд с 7
ELECTRONIX ©2004-2016