
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.21] |
![]() |
|
Страницы: (3) [1] 2 3 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Начал я изучать С++. Хотелось бы понять логику такого синтаксиса.
Объявление переменной: Имя_типа Имя_переменной; Здесь все понятно. Далее объявление указателя на переменную: Имя_Типа * Имя_Переменной; Должно же быть какое-то согласование с предыдущим правилом. Что здесь считать типом, а что именем переменой? Можно считать, что Имя_типа* есть новый производный тип, тогда все согласуется. Массив определяется так: Имя_Типа Имя_Переменной [Размер]; Массив на указатели определяется так: Имя_Типа * Имя_Переменной [Размер]; Здесь также можно считать, что Имя_типа* есть новый производный тип указателя на тип Имя_типа, тогда все согласуется. Указатель на массив определяется так: Имя_Типа (*Имя_Переменной) [Размер]; Здесь я не вижу логики. Аналогично с ссылками на функции. Конечно, эти правила можно зазубрить, но отсутствие логики меня очень расстраивает ![]() По-моему, так было бы логичнее: (Имя_Типа [Размер])* Имя_Переменной; Т.е. все согласуется с правилом объявления переменной Имя_типа Имя_переменной; Может быть нужно представить, что *Имя_Переменной - это как бы прототип операции разыменования и переменная после разыменования имеет тип Имя_Типа? Хотя все равно не вижу логики в Имя_Типа (*Имя_Переменной) [Размер]; Может все-таки кто-то может объяснить? |
![]() |
Сообщ.
#2
,
|
|
Когда-то давным-давно, то ли Кернигана, то ли Ричи, то ли обоих, что вряд ли, посетила гениальная мысль: а что если определение сущности будет иметь тот же синтаксис, что и её использование? Это позволит не вводить отдельного синтаксиса для объявлений и определений, ключевых слов и разделов в программе для этого, итп. Т.е. всё просто: вот сущность, синтаксис использования которой такой-то; чтобы её определить, достаточно её "использовать" точно так же, но предварить именем типа. Гениально. Например, определение указателя int* ptr; следует читать как "операция 'разыменования указателя', применённая к ptr, имеет результатом некий int" или более кратко "разыменовый ptr есть int". Массив: "применение операции 'индексирование' к такой-то переменной даёт такой-то тип", тут только одно специальное дополнение - вторым аргументом операции индексирования должен быть размер массива.
Постольку поскольку использование сущности обычно выполняется в неком выражении, то и определение этой сущности обычно напоминает простое выражение. А выражения, состоя их отдельных операций, естественно рассматриваются с учётом приоритетов этих операций, для дополнительного управления которыми могут использоваться скобки. Например, int *array[N], ввиду большей приоритетности [] перед *, рассматривается как "индексированный array даёт нечто, что будучи разыменованным, даёт int", а для того, чтобы получить указатель на массив int, нужно увеличить приоритетность *, применив её к array, что и делается скобками: "разыменованный array даёт нечто, что будучи индексированным, даёт int". Что касается последней, наиболее "логичной" записи (что в некотором смысле справедливо, впрочем), то она бессмысленна ибо не раскладывается в корректное выражение. Ты либо умножаешь некий элемент массива на переменную, либо разыменовываешь переменную и никакой операцией не связываешь её с предшествующим выражением в скобках. В первом случае умножение никак не может определять указатель, во втором случае имеет место просто синтаксическаая ошибка, что-то типа "ожидалась бинарная операция". |
Сообщ.
#3
,
|
|
|
Можно было ответить короче: определения переменных читаются задом-наперёд.
|
![]() |
Сообщ.
#4
,
|
|
Это было бы неправдой:
![]() ![]() int (*getOutFunc(size_t index))(const char*, ...) { static int (*funcs[])(const char*, ...) = { printf, debugOut, logOut }; return index < sizeof(funcs)/sizeof(*funcs) ? funcs[index] : NULL; } P.S. S.Eugene, ой, не ты. Звиняй ![]() |
Сообщ.
#5
,
|
|
|
Не знаю, как там с указателями на функции - их я обычно не использую, разве что при "крайней необходимости" и "с закрытыми глазами", тупой копипастой - но вот со всем остальным работает такое правило: ищешь в определении название переменной, от него идёшь сначала направо, а потом налево. Порядок меняется скобками.
То есть смотрим: ![]() ![]() int *a[12]; // массив из указателей на int int (*a)[12]; // указатель на массив int'ов int *a[12][12]; // массив массивов указателей на int int (*a[12])[12]; // массив указателей на массив int'ов Если это распространится на указатели на функции - буду только рад. Но мне они до фени... ) |
Сообщ.
#6
,
|
|
|
Цитата Значит я был прав в этой догадке про как бы разыменование. Замечательно придумано. Например, определение указателя int* ptr; следует читать как "операция 'разыменования указателя', применённая к ptr, имеет результатом некий int" или более кратко "разыменовый ptr есть int". А как для себя объясняете, что при объявлении переменных через запятую после "разыменованной" переменной все переменные считаются указателями? int x,*y,z; // z - тоже указатель Qraizer, спасибо. А то я уж думал бросить такое кривые Си учить. На душе прям полегчало ![]() |
Сообщ.
#7
,
|
|
|
S.Eugene, лучше таки брось.
есть языки куда как получше, тот же C# |
Сообщ.
#8
,
|
|
|
Цитата S.Eugene @ А как для себя объясняете, что при объявлении переменных одного через запятую после "разыменованной" переменной все переменные считаются указателями? ![]() Цитата S.Eugene @ int x,*y,z; // z - тоже указатель почему z дожен быть указателем ? ты там не видишь запятой ? или правило обявления переменных н езнаешь ? тыб почитал страуструпа чтоле бы для начала, глядишь и освоил бы... Добавлено И вообще это какаято "женская логика" мне кажеца ![]() Добавлено Цитата S.Eugene @ По-моему, так было бы логичнее: (Имя_Типа [Размер])* Имя_Переменной; интересно а вчем если не секрет тут заключаеться логика ??? |
![]() |
Сообщ.
#9
,
|
|
Цитата есть языки куда как получше, тот же C# Нравятся мне такие утверждения... ![]() Если бы один язык был бы лучше другого, тот который хуже исчез бы вообще. Например как случилось с бейсиком (не вижуал бейсик, а тот, где 10 goto 10 ![]() А раз язык есть, то он для чего-то используется и лучше приспособлен для своей задачи |
Сообщ.
#10
,
|
|
|
Цитата Hsilgos @ лучше приспособлен для своей задачи а для задач ТСа? |
![]() |
Сообщ.
#11
,
|
|
Цитата S.Eugene @ z тут никакой не указатель. А как для себя объясняете, что при объявлении переменных через запятую после "разыменованной" переменной все переменные считаются указателями? int x,*y,z; // z - тоже указатель |
Сообщ.
#12
,
|
|
|
Qraizer раскрыл тему. Но вообще, синтаксис С/С++ иногда преподносит сюрпризы. Страуструпу, кстати говоря, синтаксис С не нравился, он предлагал вводить альтернативные возможности построения конструкций, но не сложилось. Хотя в новом стандарте есть некоторые подвижки.
|
Сообщ.
#13
,
|
|
|
Цитата D_KEY @ он предлагал вводить альтернативные возможности построения конструкций, но не сложилось А как тут сложится, если при внесении breaking changes тут же начинаются вопли по поводу компилябельности legacy-кода? Думаю, кстати, после принятия нового стандарта дело (в этом отношении) пойдёт лучше, потому что изменения в синтаксисе некоторых конструкций наблюдаются весьма существенные. Тут ведь главное - начать! ![]() |
![]() |
Сообщ.
#14
,
|
|
Цитата Qraizer @ Ну, говоря "гениально", я использовал богатство и выразительность русского языка. ...вот сущность, синтаксис использования которой такой-то; чтобы её определить, достаточно её "использовать" точно так же, но предварить именем типа. Гениально. ![]() |
Сообщ.
#15
,
|
|
|
Qraizer, скорее так - теоретики в восторге, а те, кому с таким синтаксисом работать - в афиге.
|