чому як index [масив], так і масив [index] дійсні в C?

Наприклад, розглянемо:

int index = 3;
int array[4] = {0, 1, 2, 3};

тоді як index [array] та array [index] є допустимими виразами, подібно до * (index + array) і * масив + індекс) .

In C arrays why is this true? array[5] == 5[array] explains how it works. My question is: Why did the language designers choose to allow this? Why not just enforce that index[array] is invalid, for clarity's sake?

6
Зауважте, що заборона на index [array] , імовірно, введе іншу сторінку або дві до специфікації. Поточний синтаксис можна описати в рядку.
додано Автор ChrisL, джерело

6 Відповіді

Перш за все, це допоможе ознайомитись з Розробкою мови C для dmr Отримайте деякі уявлення про деякі примхи С, особливо якщо мова йде про семантику масиву (в основному, викрийте BCPL і B для більшості з них).

As for the question "[w]hy not just enforce that index[array] is invalid, for clarity's sake," what would such a check buy you in exchange for the cost of performing it? The form almost never appears outside of the IOCCC, so it's not like it's a major problem in production code (compared to the use of, say, gets, or unchecked array accesses (which disallowing i[a] won't help with), or ). It's not a bug; it doesn't introduce any undefined behavior; it doesn't introduce any security holes not already present with a[i]; the only complaints against it are stylistic in nature.

Це схоже на запитання, чому дійсно є T * p і T * p ; там немає "чому", за винятком випадків синтаксису мови. Там нічого навмисного позаду, що дозволяє обидва, це лише функція роботи граматики. Те ж саме з a [i] і i [a] . Професійні програмісти є (як правило) дорослими та не навмисне не вводять плутанини, якщо це не обґрунтовано, тому більшість, природно, використовуватиме a [i] .

Ви в основному намагаєтесь захищатись від проблеми, яка насправді не існує.

12
додано

Тому що, як і деякі інші особливості С, це просто не продумалося. Я сумніваюсь, що хтось дійсно замислювався над математичною логікою позаду масиву, що отримував у пам'яті. Однак, як виявляється, обидві операції призводять до тієї ж математики (в основному).

І містер Керран міг це сказати, але я думаю, що це не має великого значення для обчислень. Я міг би помилятися, хоча.

6
додано
Я випадково редагую на все те, що мені подобається, спасибі. Особливо коли я правий.
додано Автор mamcx, джерело
Так, цей коментар був досить конструктивним, чи не так?
додано Автор mamcx, джерело
-1 для випадкової редакції на мотивації дизайнерів С
додано Автор el2iot2, джерело
Ви вірно: ви могли б помилятися.
додано Автор Schroeder, джерело

Вибір методу array [index] мав, мабуть, виконати математичну конвенцію та прецедент, встановлений для масивів іншими мовами, такими як ALGOL, FORTRAN та BASIC (останні два використовують круглі дужки замість дужок). Це рішення робить оператора непарною качкою, оскільки він є бінарним оператором, але вимагає, щоб ви викидали додатковий токен після правого виразу.

Оператор міг би так само просто бути одним символом ( @ не говориться в C, тому назвемо його оператором додавання покажчика). Тому що, як вказує відповідь у вищезгаданому SO-питаннях Девід Торнлі, додавання покажчика є комутативним, a @ 5 і 5 @ a мають однаковий зміст. (C попередник BCPL використовує ! для цього.)

У деяких випадках природно дивитись на оператора масиву так само, як веде себе як функція, що має сенс в контексті мов, які виконують f (x) , щоб викликати функцію та a (i) для доступу до масиву. Оскільки оператори в C не працюють таким чином, ви повинні думати про це як комутативний, бінарний оператор з багажем.

5
додано
Мені подобається пояснення, трохи більш формальний може включати в себе, що масиви - це просто синтаксичний цукор покажчиків, що ще більше підсилює ваш комутативний аргумент.
додано Автор el2iot2, джерело

За словами Джеймса Керрена, причина цього полягала в тому, що при розробці C комп'ютерів було повільніше + було менше пам'яті, тому такі перевірки та оптимізація не коштували.

https://stackoverflow.com/a/381554/277800

2
додано
Це буде перевірка часу компіляції (це лівий операнд типу вказівника?), Так що це не мало значення для більшості. Це не знищило б і одноразову гарантію. Звичайно, компілятор з напівзацікавленим 70-х років може навіть ігнорувати це, але 70-ті роки були дуже ранніми в еволюції C - достатньо часу, щоб не допустити його або навчити компіляторів уникати його.
додано Автор Paul Muir, джерело
@delnan: Час компіляції все ще було великою справою ще на початку С, тому я б сказав, що це важливо (хоча особисто я б не пішов, щоб сказати, що це було причиною).
додано Автор Martin York, джерело

Це нагадує запитання, чому люди зможуть спроектувати автомобілі, які можуть вплинути на пішоходів. Вони цього не роблять. Вони розробляють машини, щоб зробити те, що їхні водії говорять їм. C був розроблений з божевільним, таємним уявленням, що програмісти відповідають за свої власні програми, і якщо вони написали щось тупу на мові програмування, то це їхня власна відповідальність. Проектні рішення помилилися на стороні видалення обмежень програміста.

1
додано
@octern - див. мою відповідь вище. Це є нестандартним поведінкою, яке випадає з субстанціональної семантики масиву (наприклад, E1 [E2] == * ((E1) + (E2)) ); єдиним обмеженням є те, що один з E1 або E2 є виразом покажчика, а інший є інтегральним виразом. Не існує обмеження, що E1 завжди є виразом покажчика, а E2 завжди - це ціле вираження. Таке обмеження могло б бути додано, але оскільки практично ніхто не використовує другу форму за межами МОКЦП, витрати на перевірку практично не користуються.
додано Автор John Bode, джерело
Ваш підхід є аргументом, чому його не потрібно змінювати, але він не відповідає на питання про те, як він отримав цей шлях. index [масив] не є ненавмисним, нестандартним поведінкою. Це було навмисно введено в мову, тому розумно питати, чому.
додано Автор octern, джерело

Напевно, ми ніколи не зможемо точно дізнатись, чому ця функція була першою, але причина того, що вона залишається на сьогоднішній день для зворотної сумісності зі старими версіями мови. Немає очевидної та переконливої ​​причини для її видалення, тому немає сенсу безоплатно порушувати існуючий код.

1
додано