Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
Здравствуйте. Сегодня изучал многомерные массивы. У меня возникла первая часть вопросов связанных с примером приведённым в главе. Привожу код, несколько изменён в связи с индексацией предложенной в книге Предварительные комментарии. Функция day_of_year возвращает порядковый номер дня по номеру месяца и дня. Функция month_day неявно возвращает день и номер месяца по году и порядковому номеру. Код: plaintext 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. 42. 43. 44. 45. 46. 0 K&Rмы поместили в начало массива day_tab столбец из нулей для того, чтобы номера месяцев изменялись естественным образом от 1 до 12, а не от 0 до 11. Так как за экономию памяти у нас пока не награждают, такой способ проще чем подгонка индексов. Мне кажется если человек понял что такое указатель, то математического аппарата для индексации хватит. Это только усложняет, на мой взгляд, нужно изменить этот код в последующих изданиях, я их к сожалению не видел. Может уже изменили. Но больше меня удивила фраза про экономию памяти. Я вообще в шоке от нее. Это сейчас я могу добавить этот вектор-столбец без проблем, но раньше ?Экономия памяти была особенно актуальна. Этот столбец я убрал тут, изменил немного индексацию, и все дела . Попутно: подскажите пожалуйста, как мне посмотреть все байты онлайн, где хранятся все элементы мои массива и тп. То есть как наблюдать за всей памятью выделенной для программы ОС онлайн. Какое-то средство при дебаге наверняка есть ? использую VS Express 2013 for Desktop 1 Для меня это выглядит как x ^ y v z, где ^ конъюнкция а v дизъюнкция. Но как это будет работать ?? ну я догадываюсь что 0^1v0 вернёт 0 например, и эта схема работает подобным образом. Верно ведь ? но почему способ определения высокосного года не year%4? 2.1-2.2 Лучше вынести в качестве глобальных переменных ? Почему да или нет ? 3.1-3.2 Ну while ведь очевидней, код второй функции я написал не смотря на то, какой код приведён и Ритчи и Кернигана, но когда увидел for, был удивлён, ведь это жутко нелогично делать тут for, очевидно это while ! Хотя for и while это одно и то-же, это я понимаю. Или в этом своя фишка которую я не понимаю ? Как вы бы поступили в таком случае ? 4 Как организовать блок 3.1/3.2 подобным образом ? Ну очень нравятся такие конструкции, жутко красивые :p 5.1-5.2 Мне уже хочется написать yd -= day_tb[leap][i++] , но правильно ли так ? На 100 ли процентов компилятор проведёт инкремент вторым действием ?? на всех машинах ? во всех ос ? Возникнет ли в данном случае неудачный пример побочного эффекта по K&R ? Да и вообще такой код мне кажется красивым, как while(*a==*b) в коде где идёт лексографическое сравнение строк(именно там, а не где его приводят K&R), но для меня очевидно, что начинающий программист который в дальнейшем будет читать мой код, может это не понять и запутаться. Ответьте на этот вопрос, и скажите как вы сами предпочитаете делать ? Пример изначально показался скучным( в который раз), но в итоге понравился ( в который раз такое) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2014, 07:19 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
0 - хватит. Но это же учебник. Для простоты изложения и чтобы лишний раз напомнить ученику что массивы начинаются с нуля... Ради этого можно и потерпеть разок избыточность. Пусть ученик сам увидит что значит начинать массивы с единицы. 1 - потому что кое-кто не знает как определяется високосный год. Угадай кто этот "кое-кто"? 2 - А зачем эти переменные в виде глобальных? Не, ну можно конечно если так хочется. Вынеси и попытайся теперь запустить любую из этих функций в цикле: Код: plaintext 1. 2. 3 - без разницы. for в таких случаях удобен тем, что инициализация и приращение переменной цикла идет рядышком с проверкой условия цикла. while - в какой-то степени чуть более логичен если принять что в for обязательно надо проверять саму переменную а не что-то основанное на ней. А что выбирать - личные предпочтения. 4 - не понял вопроса. Какой блок ты хочешь так организовать? А вообще строка 4 ужастна. Длинная и закрученная. Чтобы ее понять, ее надо читать. Беглому взгляду не доступна. 5. Читай учебник (тот самый) внимательнее. Постфиксные инкременты описаны в книге. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2014, 07:49 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
K&RМассив day_tab является первым двухмерным массивом с которым мы имеем дело. По определению в С двухмерный массив по существу является одномерным массивом, каждый элемент которого является массивом. Поэтому индексы записываются как Код: plaintext 1. 2. 3. По мне так раз по существу n-мерные массивы одномерны, то запись вторая была бы логична. Некоторый аналог сложной индексации внутри массива. Вопрос: Фраза выделенная красным подразумевает что элементы в памяти расположены друг за другом ? Вот мой тест: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. а что делает мой 060 ? Скрин прикрепил, но не понял отобразится он туту или нет сразу ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2014, 08:07 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
Пробую вывести значения двухмерного массива через указатели как будто бы работаю с линейным массивом Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. Этот код идёт по подмассивам массива ? и причём он никогда не остановится, потому не while ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2014, 08:35 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
Окей, я понял что не всё так просто как говорят Керниган и Ритчи, и я сделал так Код: plaintext 1. 2. 3. 4. 5. 6. 7. Но, почему у меня на экране только один массив ? где весь ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2014, 08:41 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
То есть он нашёл нуль внутреннего подмассива и остановился, вероятно всего так, и на 060 этот нуль как раз и находится, теперь нужно понять почему так, почему для записи с именем массива и в цикле while (*(pday_tb+i)!='\0') компилятор не понимает где конец именно этого двухмерного массива ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2014, 08:43 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
White Owl, спасибо. Я прочитал, и в нём расхождение. Потому в мою голову и закрались сомнения. Сначала должно быть использовано значение и потом будет инкремент. Но, на страницах 56-57, где как раз рассказывается про побочный эффект, написано: K&R...примером типичной неудачной ситуации является оператор Код: plaintext 1. Возникает вопрос, старое или новое значение i служит в качестве индекса. Компилятор может поступать разными способами, и в зависимости от своей интерпретации выдавать разные результаты... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2014, 09:01 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
SashaMercuryТо есть он нашёл нуль внутреннего подмассива и остановился, вероятно всего так это так потому что ты так написал '\0' значит 1 байт с кодом символа 0. т.е. просто ноль. SashaMercury компилятор не понимает где конец именно этого двухмерного массива Компилятор не должен ничего понимать. Ты объявил массив из 2 строк по 13 элементов, а проинициализировал 12 , вот компилятор туда и вставил 0 вместо недостающих. Т.е. реально получилось так: Код: plaintext 1. 2. PS у массива нет "конца" как ты ожидаешь, ты должен сам следить в коде чтобы не выйти за пределы массива. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2014, 09:10 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
А вот я дошёл до самой главной фразы в этой главе, видимо они больше всего относится к описанию 2хмерных массивов: K&RЕсли двумерный массив передается функции, то описание соответствующего аргумента функции должно содержать количество столбцов; количество строк несущественно, поскольку, как и прежде, фактически передается указатель. те я могу написать на выбор: Код: plaintext 1. 2. 3. 4. 5. 6. Судя по тому что я привёл выше из K&R, я понял что в функцию я передаю не двухмерный массив, а блок на 13 элементов(во втором и третьем случае). Мне хочется передавать только указатель на array, и всё, а дальше вертеть им как хочу. Это возможно ? Правильно ли так рассуждать ? Как делаете вы ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2014, 09:18 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
SashaMercuryВопрос: Фраза выделенная красным подразумевает что элементы в памяти расположены друг за другом ? Вот мой тест: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. а что делает мой 060 ? Скрин прикрепил, но не понял отобразится он туту или нет сразу Та же ошибка. 13 элементов а не 12. Пиши < вместо <=, тогда код понятнее будет Код: plaintext 1. 2. 3. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2014, 09:19 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
Dima T, спасибо C: Заработало, это я исправлял индексацию, убрал лишние нули, и забыл уменьшить размер массива ( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2014, 09:21 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
Dima_TТа же ошибка. 13 элементов а не 12. Пиши < вместо <=, тогда код понятнее будет дада, уже понял ( невнимательно изменил пример из K&R (( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2014, 09:23 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
Dima_TТа же ошибка. 13 элементов а не 12. Пиши < вместо <=, тогда код понятнее будет Спасибо за совет C: Индексация мне ясна , что <= что <, все ошибки пошли от размерности массива ( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2014, 09:25 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
SashaMercury... Мне хочется передавать только указатель на array, и всё, а дальше вертеть им как хочу. Это возможно ? Правильно ли так рассуждать ? Как делаете вы ? Учти что указатель дает только адрес в памяти где массив начинается, а где его конец будет неизвестно. Массив это просто непрерывный кусок памяти. Адресация в памяти линейна, поэтому любой N-мерный массив хранится как одномерный. Например если ты делаешь массив int[2][13] то выделяется 4*2*13 байт. Обращение к элементу массива это расчет адреса его хранения относительно начала. Например *a[1][6] это *a[0][0] + 1*13 + 6 Многомерными массивами не пользуюсь (не требуется), а с одномерными обычно практика такая: передается указатель на начало и размер массива (количество элементов, а не байт). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2014, 09:42 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
Запусти Код: plaintext 1. 2. это для массива day_tb[2][13] ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2014, 09:46 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
Dima_T, Вывел 16 и 17 элементы массива. Это здорово !)Сплошная индексация, или..мм. какое бы слово подобрать. Сквозная индексация, так лучше ? Или, сквозная относительная индексация. Мне нравится это свойство массивов на С ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2014, 09:56 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
По сути получение элемента a[i][j] массива a[N][M] сводится к расчету указателя на этот элемент pa = &a[0][0] + i * M + j Проверок на выход за границы массива не делается. в твоем примере 1*13 + 3 = 0*13 + 16 Главный минус использования в коде записи типа a[i][j] в потере производительности, т.к. умножение достаточно тяжелая операция для процессора. Быстрее работает если использовать указатели и сложение/вычитание для их изменения. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2014, 10:19 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
Dima_T, спасибо С: Я понял, в целом. Про високосные года, нашёл информацию, может быть кому-нибудь пригодится http://ru.wikipedia.org/ По-прежнему високосным оставался год, номер которого кратен четырём, но исключение делалось для тех, которые были кратны 100. Отныне такие годы были високосными только тогда, когда делились ещё и на 400. Иными словами, год является високосным в двух случаях: либо он кратен 4, но при этом не кратен 100, либо кратен 400. Год не является високосным, если он не кратен 4, либо он кратен 100, но при этом не кратен 400. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2014, 02:17 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
Экспериментировал сегодня. Исходя из того какая логика накладывается на n-мерные массивы f e :day_tb[1][3], day_tb[0][16], ожидал аналогичное на одномерные, но не получил то что хотел. Два вопроса: 1. Код: plaintext 1. 2. На что указывает test[16]? У меня отобразилось число порядка миллиона, вместо ожидаемой 3. 2. Почему нельзя обратиться к одномерному массиву таким образом : ar[1][2] ? Исходя из общей логики массивов на С это ожидалось ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2014, 07:34 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
SashaMercury1. Код: plaintext 1. 2. На что указывает test[16]? У меня отобразилось число порядка миллиона, вместо ожидаемой 3. Если у вас test - это двухмерный массив, то test[16] - это одномерный массив, содержащий 16-ю (17-ю по порядку) строку test. В данном случае - несуществующую строку, т.к. строк всего 2. Т.е. это выход за границы массива :) Но миллион печатается не поэтому. Т.к. test[16] - это одномерный массив, а ссылка на массив, при использовании в выражении, преобразуется в указатель 0-го элемента, то это выражение: Код: plaintext 1. эквивалентно такому Код: plaintext 1. Т.е. у вас печатается адрес приведенный к int. SashaMercury2. Почему нельзя обратиться к одномерному массиву таким образом : ar[1][2] ? Исходя из общей логики массивов на С это ожидалось Судя по всему у вас что-то не так с пониманием логики массивов на С :) Во-первых так обратиться можно, если у вас одномерный массив указателей на что-то. Во-вторых, если у вас в массиве не указатели, то конечно так обратиться нельзя. Потому что в С, к не-указателю нельзя применить операцию []. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2014, 08:23 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
SashaMercuryНа что указывает test[16]? У меня отобразилось число порядка миллиона, вместо ожидаемой 3. Это указатель, вывелся адрес ячейки test[16][0] т.е. test[16] это не 17й элемент массива, а указатель на начало 17-й строки Код: plaintext 1. 2. SashaMercury2. Почему нельзя обратиться к одномерному массиву таким образом : ar[1][2] ? Исходя из общей логики массивов на С это ожидалось Неверно ты логику понял, нельзя ее трактовать в обратном направлении. Я выше писал Dima TПо сути получение элемента a[i][j] массива a[N][M] сводится к расчету указателя на этот элемент pa = &a[0][0] + i * M + j Если ты изначально объявил одномерный массив, то как компилятор узнает чему равно M ? например 12 элементов можно считать как [3][4], [4][3], [1][12] и т.д. Если ты объявил массив двухмерным, то и работай с ним как с двухмерным. А то что можно указать индексы выходящие за пределы массива или перебрать указателем весь массив - это фича, которую надо знать и самому следить чтобы это случайно не происходило. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2014, 08:40 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
Anatoly Moskovsky, вы мне что-то не договариваете, или в K&R не договаривают. я не придавал значения операции []. это ключевая фраза. Нужно сначала понять её. Для меня a[x] это return *(a[0]+x). Но судя по вашим словам я неправильно её понимаю И сейчас вы связали напрямую указатели и массивы. То о чём я раньше спорил Anatoly MoskovskyВо-вторых, если у вас в массиве не указатели, то конечно так обратиться нельзя. Потому что в С, к не-указателю нельзя применить операцию []. Или вы выделили операцию [] отдельно. В общем я слабо понял Вас. Наверное невнимательно что-то прочитал. Сейчас попробуй найти в книге что делает операция []. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2014, 08:43 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
SashaMercuryДля меня a[x] это return *(a[0]+x). Не, это неверно (Либо у вас опечатка) Вот как компилятор это видит. Допустим есть выражение Код: plaintext 1. Так как "a" это ссылка на массив, то в выражении она заменяется на адрес 0-го элемента: Код: plaintext 1. С другой стороны выражение zzz[yyy] - это операция индексации []. Она заменяется на *(zzz + yyy). Таким образом получаем: Код: plaintext 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2014, 08:56 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
Невнимательность ( Мне Dima_T объяснял это ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2014, 09:07 |
|
||
|
K&R Многомерные массивы
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyТаким образом получаем: Код: plaintext 1. Да, тут забыл еще одно преобразование, для устранения рекурсии определения [], через самого себя. Адрес 0-го элемента &a[0] вычисляется так (element_type *)&a (т.к. адрес массива и 0-го элемента совпадают в физическом представлении) Т.е. итоговая формула такая: Код: plaintext 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2014, 09:07 |
|
||
|
|

start [/forum/topic.php?fid=57&msg=38551451&tid=2019679]: |
0ms |
get settings: |
7ms |
get forum list: |
11ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
54ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
69ms |
get tp. blocked users: |
2ms |
| others: | 12ms |
| total: | 178ms |

| 0 / 0 |
