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

 
 
4 страниц V  < 1 2 3 4 >  
Reply to this topicStart new topic
> Инициализация структуры
GetSmart
сообщение Jul 29 2018, 05:43
Сообщение #31


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(aiwa @ Jul 29 2018, 04:25) *
Из второго пункта: "The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2)))."

Явно не обозначена аргументация, зачем превращать (классическую) индексацию массива в выражение со сложением. И чем не понравился вариант, когда два (три) оператора (+/-, []) могут быть применимы к массиву. Не обозначены веские причины для того, чтобы массив стал исключением из общих правил нисходящего перемещения по агрегатным типам, когда в тексте левая часть выражения указывает на более массивный агрегатный тип. При этом массивный агр. тип является источником имён и прочей инфы для нисхождения. Для массива это правило интуитивно оптимально при обращениях к многомерным массивам. Здесь же "E1[E2] is identical to (*((E1)+(E2)))" контроль диапазонов многомерия либо невозможен, либо возможен только контроль суммарного размера массива. Плюс, все операторы ".", "->" являются ассиметричными к операндам, аналогично "[]" в большинстве ЯП, изучаемых в образовательных учреждениях. Это правило делает и работу компилятора и читабельность текста проще.

С таким стандартом руки чешутся писать E1[E2]E3[E4] и прочую ерунду. Опять же, ++E1[E2] , где E2 - массив, E1 - integer lvalue, - выносит мозг конкретно. Хочется инкрементнуть элемент массива, но читается по естественным правилам это как увеличение индекса. Плюс: E1++[E2]++. Если ещё покопать, то можно мумию Тутанхамона выкопать.

Сообщение отредактировал GetSmart - Jul 29 2018, 20:30


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Jul 29 2018, 07:14
Сообщение #32


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

Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(GetSmart @ Jul 29 2018, 08:43) *
Плюс, все операторы ".", "->" являются ассиметричными к операндам, аналогично "[]" в большинстве ЯП, изучаемых в образовательных учреждениях. Это правило делает и работу компилятора и читабельность текста проще.
Когда содавался язык Си, никаких
Цитата
ЯП, изучаемых в образовательных учреждениях
не было.
Go to the top of the page
 
+Quote Post
aiwa
сообщение Jul 29 2018, 08:38
Сообщение #33


Местный
***

Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682



Цитата(GetSmart @ Jul 29 2018, 08:43) *
Явно не обозначена аргументация, зачем превращать (классическую) индексацию массива в выражение со сложением.

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

Цитата(GetSmart @ Jul 29 2018, 08:43) *
Здесь же "E1[E2] is identical to (*((E1)+(E2)))" контроль диапазонов многомерия либо невозможен, либо возможен только контроль суммарного размера массива.

По сути "E1[E2] is identical to (*((E1)+(E2)))" - это лишь выражение идеи. Для полной идентичности целое E2 должно быть умножено на типоразмер E1.
Идея состоит в том, что имя массива страдает дуализмом: оно указывает на первый элемент массива но не является указателем в нормативном смысле.
Отсюда естественно вытекает определение многомерных массивов: показывает на элемент, который является массив меньшей размерности.
Поэтому контроль диапазонов вполне возможен и, в принципе, легко реализуем, но, к всеобщему счастью, априори не предусмотрен в С.

Цитата(GetSmart @ Jul 29 2018, 08:43) *
С таким стандартом руки чешутся писать E1[E2]E3[E4] и прочую ерунду. Опять же, ++E1[E2] , где E2 - массив, E1 - integer lvalue, - выносит мозг конкретно. Хочется инкрементнуть элемент массива, но читается по естественным правилам это как увеличение индекса. Плюс: E1++[E2]++. Если ещё покопать, то можно мумию Тутанхамона выкопать.

++E1[E2] - это и есть по естественным правилам инкрементация элемента массива E1[E2].
А вот E1++[E2]++ не сработает. Нужно писать (E1+1)[E2]++;
E1[E2]E3[E4], понятное дело не имеет смысла как и написанные слитно два имени переменных.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Aug 2 2018, 02:41
Сообщение #34


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(andrew_b @ Jul 29 2018, 11:14) *
Когда содавался язык Си, никаких {ЯП, изучаемых в образовательных учреждениях} не было.

Да, но тогда переформулируя, в большинстве ЯП высокого уровня того времени.

----------------
Как сказал один мой необкуренный коллега: Что-то у вас тут недоработано ©

Ещё, надеюсь, в стандарте кто-нибудь догадался однозначно указать, что в разделе кода точка с запятой после закрытия непустого блока (}) выражением не считается. (из-за которого предыдущие IF потеряют возможность иметь ELSE)

Upd. И это, разумеется, не касается блока инициализатора. Ещё лучше так: ... указать, что точка с запятой, интерпретируемая первым оператором после закрытия непустого блока кода (закр. фиг. скобки), - выражением не считается.

Отпуск на носу. Отложу раскопки на потом.

Сообщение отредактировал GetSmart - Aug 2 2018, 13:32


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Aug 2 2018, 04:51
Сообщение #35


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

Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(GetSmart @ Aug 2 2018, 05:41) *
Да, но тогда переформулируя, в большинстве ЯП высокого уровня того времени.
А много ли их тогда было вообще?
Цитата(GetSmart @ Aug 2 2018, 05:41) *
Ещё, надеюсь, в стандарте кто-нибудь догадался однозначно указать, что в разделе кода точка с запятой после закрытия блока (}) выражением не считается. (из-за которого предыдущие IF потеряют возможность иметь ELSE)
А с чего бы? Это пустой оператор. Он тоже подчиняется всем правилам.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Aug 2 2018, 05:39
Сообщение #36


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(andrew_b @ Aug 2 2018, 08:51) *
А с чего бы? Это пустой оператор. Он тоже подчиняется всем правилам.

Это удобно для макросов, кои были задуманы сразу же на заре Си. Чтобы не требовалась (ужжасная) обёртка do...while(0).

ps
в пред пост вставил <непустого>, т.к. часто видел и даже сам раньше употреблял {}; в чём-то вроде while (...) {};

Сообщение отредактировал GetSmart - Aug 2 2018, 05:45


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Aug 2 2018, 06:53
Сообщение #37


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

Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



При чём тут непустой блок? Пустой оператор -- это ;. Для всех операторов правила общие.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Aug 2 2018, 12:04
Сообщение #38


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Там немного обновил.

Отвечу так: одной из важнейших целей правил является компактность и ясность программы. Если это требует маленького исключения/особенности, то ничего плохого в этом нет. Которые там и так есть. Это точно менее кошмарно, чем index[array] и мутный do {...} while (0) в макросе. Кроме того, предельная простота совсем не гарантирует однозначности (толкования).


Цитата(aiwa @ Jul 29 2018, 12:38) *
По сути "E1[E2] is identical to (*((E1)+(E2)))" - это лишь выражение идеи. Для полной идентичности целое E2 должно быть умножено на типоразмер E1.
Идея состоит в том, что имя массива страдает дуализмом: оно указывает на первый элемент массива но не является указателем в нормативном смысле.
Отсюда естественно вытекает определение многомерных массивов: показывает на элемент, который является массив меньшей размерности.
Поэтому контроль диапазонов вполне возможен и, в принципе, легко реализуем, но, к всеобщему счастью, априори не предусмотрен в С.

Подскажите тогда, какой тип будут иметь вполне корректные выражения: (при E2=array, E1=index, для одномерного и многомерного массивов)
1: ((E1)+(E2))
2: ((E1)+(E2)+5)
3: ((E1)+5+(E2))
И, если можете, дайте определение/цитату или ссыль на упомянутый термин <типоразмер E1> в тексте <целое E2 должно быть умножено на типоразмер E1>. Это размер элемента ниже по иерархии от имени или размер элемента "на самом дне массива"? Или даже размер целого массива, на который указывает имя? (<типоразмер short> я буквально понимаю как 2 байта {например в Keil for ARMv4..ARMv7}. Типоразмер E5, где E5=структура, я склонен толковать как размер всей структуры, и по этой причине типоразмер E1 (ака массива) - как всего массива целиком. Для версии <имя массива в какой-то мере адрес> считать типоразмером E1 размер адреса - в обсуждаемом контексте вообще маловероятно).

Сообщение отредактировал GetSmart - Aug 2 2018, 14:03


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
aiwa
сообщение Aug 2 2018, 14:00
Сообщение #39


Местный
***

Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682



Цитата(GetSmart @ Aug 2 2018, 15:04) *
Подскажите тогда, какой тип будут иметь вполне корректные выражения: (при E2=array, E1=index, для одномерного и многомерного массивов)
1: ((E1)+(E2))
2: ((E1)+(E2)+5)
3: ((E1)+5+(E2))


1. указатель на E1-й элемент массива E2.
2. и 3. указатель на (E1+5)-й элемент массива E2.

В случае многомерности E2 элементом будет выступать массив размерности меньшей на единицу, чем E2 .

Когда я говорил про типоразмеры я имел ввиду упомянутые выше ассемблерные команды.
Компилятор С сложение в этих выражениях понимает в смысле арифметики указателей и все получается корректным.



Go to the top of the page
 
+Quote Post
GetSmart
сообщение Aug 2 2018, 14:17
Сообщение #40


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(aiwa @ Aug 2 2018, 18:00) *
1. указатель на E1-й элемент массива E2.
2. и 3. указатель на (E1+5)-й элемент массива E2.

В случае многомерности E2 элементом будет выступать массив размерности меньшей на единицу, чем E2 .

В стандарте пример подобный описан или какие-то комментарии разработчиков прилагаются?

Мне непонятно, для массива определены особые правила вычисления выражений? По стандартным/общим правилам для варианта 2 будет сперва выполнено (E1)+(E2) и результатом будет (как заявлено в цитате из стандарта) - адрес элемента массива. При многомерном массиве - адрес массива <размерности меньшей на единицу, чем E2>. И уже когда к этому аргументу будет приплюсовываться число 5, то оно, проще говоря, должно быть (наиболее вероятно по вышеобозначенной инфе) индексом следующей (второй) размерности. Однако, если массив одномерный, то добавление числа к адресу, указывающему не на массив, истолкуется как добавление числа к указателю такого типа. И результат для одномерного массива будет действительно похож на <2. и 3. указатель на (E1+5)-й элемент массива E2.>

Сообщение отредактировал GetSmart - Aug 2 2018, 14:55


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
aiwa
сообщение Aug 2 2018, 14:50
Сообщение #41


Местный
***

Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682



Цитата(GetSmart @ Aug 2 2018, 17:17) *
Мне непонятно, для массива определены особые правила вычисления выражений? По стандартным/общим правилам для варианта 2 будет сперва выполнено (E1)+(E2) и ....


Так все это E2+E1 и подобные выражения не являются исходным для применения правил, они лишь объясняют использование "array subscripting".

Грубо говоря, они помогают понимать как компилятор должен обходиться с выражениями вида expr1[expr2] и подобными.

Если E2 - многомерный массив, например E2[10][20][30][40][50]
2. и 3. варианты подходят к случаю E2[E1+5], результатом которого будет (E1+5)-й подмассив типа ()[20][30][40][50];
Для E2[E1][5] выражение будет композицией вышеупомянутого правила: сначала получается из "E2[E1]" (E1)-й подмассив типа ()[20][30][40][50] - грубо говоря к адресу E2 прибавляется E1*типоразмер ()[20][30][40][50], и затем к полученному результату правило применяют повторно для [5] - здесь уже арифметика указателей должна прибавлять пять типоразмеров меньшей размерности ()[30][40][50].

Под типразмером я имею ввиду физический размер с учетом выравнивания.

В стандарте, наверное, нет никаких типоразмеров, он оперирует "элементами массива", вводя многомерность по рекурсии.






Go to the top of the page
 
+Quote Post
GetSmart
сообщение Aug 2 2018, 15:00
Сообщение #42


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(aiwa @ Aug 2 2018, 18:50) *
Так все это E2+E1 и подобные выражения не являются исходным для применения правил, они лишь объясняют использование "array subscripting".

Грубо говоря, они помогают понимать как компилятор должен обходиться с выражениями вида expr1[expr2] и подобными.

В вышеобсуждаемой цитата из стандарта явно указано, что такое выражение разрешено стандартом (сложение чисел с именем массива). При неуказании особых правил этого "изврата" применяются стандартные правила приоритетов и ассоциативности. Без оговорок и комментариев на уровне стандарта иначе это нельзя истолковать.


Лучше даже уточнить:
Цитата
По стандартным/общим правилам для варианта 2 будет сперва выполнено (E1)+(E2) и результатом будет (как заявлено в цитате из стандарта) - адрес элемента массива. При многомерном массиве - адрес массива <размерности меньшей на единицу, чем E2>. И уже когда к этому аргументу будет приплюсовываться число 5, то оно, проще говоря, должно быть (наиболее вероятно по вышеобозначенной инфе) индексом следующей (второй) размерности. Однако, если массив одномерный, то добавление числа к адресу, указывающему не на массив, истолкуется как добавление числа к указателю такого типа.

<Адрес> точнее будет заменить на <что-то> (неуказанное в стандарте), содержащее адрес, указывающий на вышеобозначенный тип. (пример: <сперва выполнено (E1)+(E2) и результатом будет {как заявлено в цитате из стандарта} - адрес элемента массива.> ==> <что-то> с адресом элемента массива) И к этому <что-то> применим оператор *. К указателю он тоже применим, но их идентичность это не доказывает, без документального подтверждения.

Свой пред пост дополнил.

Сообщение отредактировал GetSmart - Aug 2 2018, 16:00


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
aiwa
сообщение Aug 2 2018, 15:53
Сообщение #43


Местный
***

Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682



Цитата(GetSmart @ Aug 2 2018, 18:00) *
В вышеобсуждаемой цитата из стандарта явно указано, что такое выражение разрешено стандартом (сложение чисел с именем массива).


Если уж быть корректным, то сложение чисел не с именем массива, а с указателем (на тип элементов из которых состоит массив), в качестве которого выступает имя массива и равным алресу его "инициирующего элемента".




Цитата(GetSmart @ Aug 2 2018, 18:00) *
<Адрес> точнее будет заменить на <что-то> (неуказанное в стандарте), содержащее адрес, указывающий на вышеобозначенный тип. (пример: <сперва выполнено (E1)+(E2) и результатом будет {как заявлено в цитате из стандарта} - адрес элемента массива.> ==> <что-то> с адресом элемента массива) И к этому <что-то> применим оператор *.


В стандарте в качестве этого <что-то> употребляют термин "роinter". Это к тому, из-за чего весь сыр-бор пошел.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Aug 2 2018, 16:49
Сообщение #44


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(aiwa @ Aug 2 2018, 19:53) *
В стандарте в качестве этого <что-то> употребляют термин "роinter". Это к тому, из-за чего весь сыр-бор пошел.

Туда же добавил
<К указателю он тоже применим, но их идентичность это не доказывает, без документального подтверждения.>

Цитата(aiwa)
Если уж быть корректным, то сложение чисел не с именем массива, а с указателем (на тип элементов из которых состоит массив), в качестве которого выступает имя массива и равным алресу его "инициирующего элемента".


Сложение с именем массива:
result = *(array+5)

Сложение с указателем (на тип элементов из которых состоит массив):
result = *(&array[0]+5)

В цитате было (буквально) сложение с именем массива.

Цитата
The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2)))

Переводится как <Определением <subscript operator []> является то, что {неявно подразумевается: выражение} E1[E2] идентично {выражению} (*((E1)+(E2)))>
Цитата
И далее объяснение - потому что "E1 is an array object (equivalently, a pointer to the initial element of an array object)".

Из чего следует, что в текстах разрешено использовать выражения со сложениями целых чисел с именами массивов. Без оговорок на размерность массивов.

Upd: А ещё точнее: с такими же ограничениями как и для оператора [].
Всё это не исключает при сложениях и такой возможности: при невозможности к аргументу применить оператор [], могут быть применены другие правила (если они определены), как то: трансформация аргумента в указатель и сложение с этим указателем.

То, что в определении имя заключено в круглые скобки - сути не меняет, т.к. в этом выражении они являются оператором изменения очерёдности выполнения других операторов. (чорт его знает как скобки там дословно определили) И (array)[index] по смыслу исполнения равноценно array[index], когда внутри скобок нет операторов. {неявно подразумевая: в тексте после препроцессора}

-------------
Дежа-вю
Цитата(Сергей Борщ)
От перемены мест слагаемых сумма не меняется.

Цитата
Не надо гипотез. В стандарте все описано. И неявные преобразования, и коммуникативность сложения.


Сообщение отредактировал GetSmart - Aug 3 2018, 08:01


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Aug 3 2018, 05:01
Сообщение #45


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

Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(GetSmart @ Aug 2 2018, 19:49) *
Туда же добавил
Вы это прекращайте. С постоянными правками предыдущих сообщений трудно следить за дискуссией.
Цитата
<К указателю он тоже применим, но их идентичность это не доказывает, без документального подтверждения.>
Почему бы вам самим взять и не почитать стандарт языка Си? hint: google://ansi_c.pdf
Go to the top of the page
 
+Quote Post

4 страниц V  < 1 2 3 4 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th April 2024 - 00:52
Рейтинг@Mail.ru


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