Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Указатели на строку в С
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Страницы: 1, 2
psL
В Си есть два способа определения строки:

Код
    char str[] = "string";
    void* p1= str;
    void* p2=&str;
    void* p3=&str[0];

    printf("%p\n%p\n%p\n",p1,p2,p3);

$ a.out
0xbfaa14c5
0xbfaa14c5
0xbfaa14c5


    char* str = "string";
    void* p1= str;
    void* p2=&str;
    void* p3=&str[0];

    printf("%p\n%p\n%p\n",p1,p2,p3);

$ a.out
0x80488bc
0xbfc25c78
0x80488bc


В первом случае p1 равен p2. Почему так?
amaora
В первом случае нет переменных хранящих адрес массива, чтобы получить &str как во втором случае эту переменную пришлось бы создать и выдать ее адрес.
Сергей Борщ
Цитата(psL @ Jan 24 2016, 10:04) *
В Си есть два способа определения строки:
Да, но они другие. Эти способы - "abcd" и { 'a', 'b', 'c', 'd','\0'}. Вы же объявили строку одним и тем же способом, более того - в обоих случаях вы продемонстрировали неявное приведение массива к указателю на его первый элемент. Просто во втором случае вы это приведение сделали при объявлении переменной str, а в первом - при объявлении указателей px. В первом случае у вас str - это массив. Во втором случае у вас массив имени не имеет, но существует переменная str, хранящая указатель на его первый элемент.
zltigo
QUOTE (amaora @ Jan 24 2016, 12:17) *
В первом случае нет переменных хранящих адрес массива, чтобы получить &str как во втором случае эту переменную пришлось бы создать и выдать ее адрес.

Потому, что в первом примере определена строка, а во втором УКАЗАТЕЛЬ на строку.

А вопрос-то был о другом.
Все три выражения в первом случае это есть одно и тоже, поскольку имя переменной это есть ее адрес, то указание взятия адреса есть масло маслянное. Для масивов адрес массива есть адрес его нулевого элемента, посему допронительное указание взять адрес именно нулевого есть уже масло маслянное для масла маслянного.
_Ivan_33
а почему 2?
а строковый литерал типа
#define MSG "BLA BLA BLA"
?
psL
Цитата(Сергей Борщ @ Jan 24 2016, 13:32) *
Да, но они другие. Эти способы - "abcd" и { 'a', 'b', 'c', 'd','\0'}.

чем отличается = { 'a', 'b', 'c', 'd','\0'} от = "abcd" ? пмсм: ничем.
Код
        const char str[] = { 's','t','r','i','n','g', 0 };
        void* p1= str;
        void* p2=&str;
        void* p3=&str[0];

        printf("%p\n%p\n%p\n",p1,p2,p3);
$a.out
0xbff1a729
0xbff1a729
0xbff1a729

Почему указатель на начало массива p1 и указатель на этот указатель имеют одно и тоже значение?

Почему не вот так работает?
Код
const char str[] = { 's','t','r','i','n','g', 0 };
        void* p1= str;
        void* p2=&p1; //&str;
        void* p3=&str[0];

        printf("%p\n%p\n%p\n",p1,p2,p3);
$a.out
0xbf88cc09
0xbf88cc04
0xbf88cc09



Цитата(_Ivan_33 @ Jan 24 2016, 14:10) *
а почему 2?
а строковый литерал типа
#define MSG "BLA BLA BLA"
?

ну может и больше. Интересуют эти 2. В вашем примере строка не будет создаваться программой вплоть до char* str=MSG , например

Цитата(amaora @ Jan 24 2016, 13:17) *
В первом случае нет переменных хранящих адрес массива, чтобы получить &str как во втором случае эту переменную пришлось бы создать и выдать ее адрес.

разве имя массива без индекса не является указателем на первый член этого массива? непонятно.
zltigo
QUOTE (psL @ Jan 24 2016, 13:26) *
Почему указатель на начало массива p1 и указатель на этот указатель одно и тоже число?

С какого бодуна? Вы сами-же на себя написали опровержение:
QUOTE
CODE
        void* p1= str;
        void* p2=&p1; //&str;
        void* p3=&str[0];

        printf("%p\n%p\n%p\n",p1,p2,p3);
$a.out
0xbf88cc09
0xbf88cc04
0xbf88cc09

В этом Вашем-же примере p1 это "указатель на начало массива"? А p2 "указатель на этот указатель". Соответственно это два РАЗНЫХ объекта и имеют "разные числа", что и видно в Вашей-же распечатке.
Начните с чтения K&R. Ну ОЧЕНЬ помогает.
Аминь.
SSerge
Цитата(psL @ Jan 24 2016, 18:26) *
чем отличается = { 'a', 'b', 'c', 'd','\0'} от = "abcd" ? пмсм: ничем.

Таки отличается.
Код
void foo1( char* s );
void foo2( char c );

void foo3( int i )
{
    foo1( "1234");
    foo2( "ABCD"[i] );
}

а вот с { 'a', 'b', 'c', 'd','\0'} такой фокус не проходит.
psL
Цитата(zltigo @ Jan 24 2016, 14:34) *
В этом Вашем-же примере p1 это "указатель на начало массива"? А p2 "указатель на этот указатель". Соответственно это два РАЗНЫХ объекта и имеют "разные числа", что и видно в Вашей-же распечатке. Аминь.
Начните с чтения K&R. Ну ОЧЕНЬ помогает.

Где аминь? Почему p1 == p2 в случае p2 = &str ; при char str[] = "blablabla" ? Без K&R обьяснить можете? laughing.gif
zltigo
QUOTE
(psL @ Jan 24 2016, 13:42) *
Без K&R обьяснить можете? laughing.gif

Могу. Вот Вам УЖЕ был дан ответ:
QUOTE
Все три выражения в первом случае это есть одно и тоже, поскольку имя переменной это есть ее адрес, то указание взятия адреса есть масло маслянное. Для масивов адрес массива есть адрес его нулевого элемента, посему допронительное указание взять адрес именно нулевого есть уже масло маслянное для масла маслянного.

Но, очевидно, что для понимания Вам придется начать с букваря для первого класса и вообще научится читать. После чего уже сможете читать в том числе и K&R и уже подумать и понять что делает операнд '=' и что делает операнд '&' получив адрес обьекта.
amaora
Цитата(psL @ Jan 24 2016, 14:26) *
разве имя массива без индекса не является указателем на первый член этого массива? непонятно.


Выражение "имя массива без индекса" имеет тип указателя на элемент массива, значение соответствует адресу первого члена. Но это не переменная-указатель, собственного адреса у этого выражения нет. В таблице символов компилятора есть только переменная "массив", со своим адресом, а вы хотите получить адрес переменной где хранится указатель на "массив", такого нигде нет.

Может стоит разобраться как этот код в памяти располагается, если есть непонимание.
psL
Цитата(zltigo @ Jan 24 2016, 14:51) *
Все три выражения в первом случае это есть одно и тоже, поскольку имя переменной это есть ее адрес, то указание взятия адреса есть масло маслянное. Для масивов адрес массива есть адрес его нулевого элемента, посему допронительное указание взять адрес именно нулевого есть уже масло маслянное для масла маслянного.
Но, очевидно, что для понимания Вам придется начать с букваря для первого класса и вообще научится читать...

да это какая-то петросянщина маслом масляная.
Можете кратко и грамотно безграмотному мне обьяснить? Без букваря, петросяна и тд ?
Код
  char s[]="abc";
  void* p1 = s;
  void* p2 = &s;
  void* p3 = &p1;

Почему равны p1 и p2? Почему не равны p2 и p3?


Цитата(amaora @ Jan 24 2016, 15:13) *
Выражение "имя массива без индекса" имеет тип указателя на элемент массива, значение соответствует адресу первого члена. Но это не переменная-указатель, собственного адреса у этого выражения нет. В таблице символов компилятора есть только переменная "массив", со своим адресом, а вы хотите получить адрес переменной где хранится указатель на "массив", такого нигде нет.

Спасибо. Более-менее понятно.
GetSmart
Wow!
Индекс разрешили применять к rvalue?

Цитата(SSerge @ Jan 24 2016, 15:36) *
Таки отличается.
Код
void foo1( char* s );
void foo2( char c );

void foo3( int i )
{
    foo1( "1234");
    foo2( "ABCD"[i] );
}

Какой компилятор так умеет извращаться? sm.gif
gerber
Цитата(psL @ Jan 24 2016, 15:46) *
Можете кратко и грамотно безграмотному мне обьяснить? Без букваря, петросяна и тд ?
Код
  char s[]="abc";
  void* p1 = s;
  void* p2 = &s;
  void* p3 = &p1;

Почему равны p1 и p2? Почему не равны p2 и p3?

Вы присваиваете УКАЗАТЕЛЮ p1 ЗНАЧЕНИЕ массива символов s - поэтому происходит неявное преобразование имени массива s в ссылку на него, то есть в &s. В случае p2 это написано явно. Поэтому значения p1 и p2 равны. А p3 содержит АДРЕС переменной p1, поэтому никакого отношения к ЗНАЧЕНИЮ переменной p1 не имеет.
Сергей Борщ
Цитата(GetSmart @ Jan 24 2016, 14:54) *
Какой компилятор так умеет извращаться? sm.gif
Любой выполняющий требования стандарта.
GetSmart
Цитата(Сергей Борщ)
Любой выполняющий требования стандарта.

То есть по стандарту индекс можно применять к rvalue? Уточняю. Или по-другому заявлено? Это с чистого как слеза Си так задумано?
zltigo
QUOTE (GetSmart @ Jan 24 2016, 15:17) *
То есть по стандарту индекс можно применять к rvalue?

Причем тут все это? Просто

foo2( "ABCD"[i] );

это, естественным образом, абсолютно тоже самое, что

char str[] = "ABCD";
foo2( str[i] );

Смотрится, конечно, страновато, но законно.
Сергей Борщ
Цитата(GetSmart @ Jan 24 2016, 15:17) *
То есть по стандарту индекс можно применять к rvalue? Уточняю. Или по-другому заявлено? Это с чистого как слеза Си так задумано?
Если речь идет о записи "строковый литерал"[индекс], то да - это чистый, как слеза Си. Строковый литерал неявно приводится к указателю на char const, а для указателя определены индексные операции, которые есть адресная арифметика. Отсюда в чистом как слеза Си возможно и такая запись: i["abcdef"].
GetSmart
Цитата(zltigo @ Jan 24 2016, 17:51) *
Смотрится, конечно, страновато, но законно.

Незаконно. Классификация lvalue/rvalue (ака переменная/значение) не позволяет такие вольности. По логике, это как взять адрес от значения. Бред. Компилятор должен ругаться на этапе компиляции.

Цитата(Сергей Борщ @ Jan 24 2016, 17:55) *
Строковый литерал неявно приводится к указателю на char const

В стандарте чёрным по белому написано, что прямо внутри разбора выражения? Логично когда оно преобразуется после завершения выражения. Как и с приведением имени массива. Применение амперсанда к массиву естественно, по аналогии со всеми остальными переменными.
gerber
"ABCD" не является rvalue, строго говоря. Это константа, для которой отведено место в памяти, значит и адрес можно брать, и индекс. А rvalue не видны за пределами выражения, в котором они используются.
krux
Цитата(GetSmart @ Jan 24 2016, 17:05) *
Классификация lvalue/rvalue (ака переменная/значение) не позволяет такие вольности.

покажите каким образом "ABCD" по-вашему является rvalue, со ссылкой-цитатой на стандарт.
GetSmart
Цитата(gerber @ Jan 24 2016, 18:16) *
"ABCD" не является rvalue, строго говоря. Это константа, для которой отведено место в памяти, значит и адрес можно брать, и индекс. А rvalue не видны за пределами выражения, в котором они используются.

И сложение rvalue-строк на этапе компиляции отменили?

Цитата(krux @ Jan 24 2016, 18:20) *
покажите каким образом "ABCD" по-вашему является rvalue, со ссылкой-цитатой на стандарт.

Вообще-то очевидно, что оно есть rvalue. А вот когда происходят неявные преобразования это другой вопрос. Оно не может происходить сразу по завершающим кавычкам. По аналогии с массивом, применение индекса к имени массива не вызывает неявное преобразование. Не видно оснований почему к строке оно должно вызывать.
krux
Цитата(GetSmart @ Jan 24 2016, 17:22) *
Цитата
покажите каким образом "ABCD" по-вашему является rvalue, со ссылкой-цитатой на стандарт.

Вообще-то очевидно, что оно есть rvalue.

нет.
GetSmart
Дополнил конец пред поста.
krux
Цитата(GetSmart @ Jan 24 2016, 17:22) *
Вообще-то очевидно, что оно есть rvalue. А вот когда происходят неявные преобразования это другой вопрос. Оно не может происходить сразу по завершающим кавычкам. По аналогии с массивом, применение индекса к имени массива не вызывает неявное преобразование. Не видно оснований почему к строке оно должно вызывать.

Цитата(GetSmart @ Jan 24 2016, 17:27) *
Дополнил конец пред поста.

разницы не вижу.
ни ссылок, ни цитат, зато бушует подмена стандарта вашими "понятиями", "аналогиями" и якобы "очевидностями".
Сергей Борщ
Цитата(GetSmart @ Jan 24 2016, 16:05) *
В стандарте чёрным по белому написано, что прямо внутри разбора выражения?
Да, как и все остальные неявные приведения типов.
Цитата(GetSmart @ Jan 24 2016, 16:22) *
И сложение rvalue-строк на этапе компиляции отменили?
Это как?
GetSmart
Цитата
Это как?

foo2( "ABCD" + "XYZ" );

Неявное преобразование происходит строго после полного завершения выражения - первого аргумента функции.
zltigo
QUOTE (GetSmart @ Jan 24 2016, 17:02) *
foo2( "ABCD" + "XYZ" );

Неявное преобразование происходит строго после полного завершения выражения - первого аргумента функции.

C дуба рухнули?
Здесь Вам не Паскаль. Здесь, если хочется, то
foo2( "ABCD" "XYZ" );
И это из другой оперы.

Сергей Борщ
Цитата(GetSmart @ Jan 24 2016, 17:02) *
foo2( "ABCD" + "XYZ" );
Я даже скомпилил от неожиданности. Не, все нормально:
Код
char const * a = "ab" + "cd";

Compiling: test.c
test.c:2:23: error: invalid operands to binary + (have 'char *' and 'char *')
char const * a = "ab" + "cd";
                       ^

Вы в следующий раз проверяйте перед тем как писать.


GetSmart
Если строки складываются без плюса, то я не сильно ошибся.
Загвоздка собственно в приоритете неявного преобразования при разборе выражения. Но я упустил аналогию с применением индекса к lvalue-указателю, который вызывает неявное преобразование раньше индексирования. Против такого козыря у меня ничего нет. Недоглядел.

Паскалем балуюсь, немножко sm.gif
zltigo
QUOTE (GetSmart @ Jan 24 2016, 17:30) *
Если строки складываются без плюса, то я не сильно ошибся.

Да они вообще не складываются. Это строку так допустимо записывать.
GetSmart
Тогда есть отличия с взятием адреса массива через амперсанд и взятием адреса строки. Имя массива амперсанд неявно не преобразует к адресу первого элемента, а к строке амперсанд делает неявное преобразование и создаёт или находит уже готовое lvalue, от которого и берёт адрес. Причём взятие адреса массива мне кажется естественным и явно аналогично взятию адреса любой переменной. А вот амперсанд со строкой до сих пор не видел в текстах, которые читал.

Цитата(krux @ Jan 24 2016, 18:38) *
ни ссылок, ни цитат, зато бушует подмена стандарта вашими "понятиями", "аналогиями" и якобы "очевидностями".

Признаю ошибку. Строка (в кавычках) в Си не есть обычное rvalue. Паскаль меня попутал.
Я копал не столько стандарт, сколько конфликты и обоснованность семантики. Тема реально похожа на разбор семантики слов и предложений обычного языка.

--------------
Видел где-то объявление массивов в аргументах функций при их вызове. Всё ли там чисто.
GetSmart
Цитата(Сергей Борщ @ Jan 24 2016, 17:55) *
Если речь идет о записи "строковый литерал"[индекс], то да - это чистый, как слеза Си. Строковый литерал неявно приводится к указателю на char const, а для указателя определены индексные операции, которые есть адресная арифметика. Отсюда в чистом как слеза Си возможно и такая запись: i["abcdef"].

Конец цитаты точно верный?

В индексировании строки будет аж два подряд неявных преобразования. На этом стандарт должен акцентировать внимание. Сперва строка создаст lvalue и значение превратится в указатель, а потом указатель должен неявно превратиться переменную, к которой применим индекс. Т.к. такое выражение полнейшая экзотика, то какие-то компиляторописатели могли бы встать на грабли, если в стандарте нет подсказки.

Т.к. неявное преобразование строки происходит в указатель на char, то таки одно неявное преобразование. Индексирование указателя на массив и указателя на другой не пустой тип происходит по-разному. Опять в свой огород закинул.
Сергей Борщ
Цитата(GetSmart @ Jan 24 2016, 19:28) *
Конец цитаты точно верный?
Точно. Зуб даю. Ну слегка опечатался: должно было быть "возможна".

Цитата(GetSmart @ Jan 24 2016, 19:28) *
а потом указатель должен неявно превратиться переменную, к которой применим индекс.
Откройте стандарт и почитайте, что делает оператор индекса. Стандарт легко гуглится.

Цитата
A postfix expression followed by an expression in square brackets [] is a subscripted
designation of an element of an array object. The definition of the subscript operator []
is that E1[E2] is identical to (*((E1)+(E2)))
.
От перемены мест слагаемых сумма не меняется.
GetSmart
Цитата(Сергей Борщ @ Jan 24 2016, 22:45) *
От перемены мест слагаемых сумма не меняется.

По поводу выделенного в цитате. Если бы там вместо definition было "действие", то всё было бы корректно к асимметрии взятия элемента массива. Т.к. в предыдущем предложении она обозначена и наследуется следующим предложением. В таком виде как написано толковать его можно как допускающее перемену мест двух выражений у оператора [], если в описании оператора "+" не указана явно зависимость результата от перестановки слагаемых обсуждаемых типов. (насколько это определение старое? в нете коментарии о New C standard)

Касательно семантики идеального Си, без всяких плюшек и перегрузок Си++.

В сложении чисел перемена мест слагаемых унаследована из математики. Т.к. к указателю удобно применять сложение, то разрешив его логично и наследование правила перемены мест слагаемых, если какого-то альтернативного результата не может быть, например из-за (гипотетических) неявных преобразований указателя в число (или адрес или содержимое памяти) когда по соседству у него "третьим" (первые два - число и указатель) будет оператор или операнд, требующий данное неявное преобразование. У понятия взятия элемента массива обычно две составные части выражения исходно разнотипные и это действие семантически несимметричное. Например, как in в Паскале. Оснований делать его симметричным в Си не обозначено, а усложнение читабельности и искажение понятия налицо. Здесь асиметрия сильно увеличивает безопасность. В том же стандарте Си наверняка в разделе объявлений переменных (конкретно массивов) указано (например неявно), что нет никакой симметрии и имя массива всегда вне []. Без наличия оснований ввода в стандарт симметрии операндов оператора [] в разделе statement, стандарт будет кривым. Прямо в Си-стандарте, а не в стандарте "соседнего" языка.
Сергей Борщ
Цитата(GetSmart @ Jan 25 2016, 05:21) *
По поводу выделенного в цитате. Если бы там вместо definition было "действие",
definition = определение. То есть операция [] определяется и работает именно так, только так и никак иначе.

Цитата(GetSmart @ Jan 25 2016, 05:21) *
если какого-то альтернативного результата не может быть, например из-за (гипотетических) неявных преобразований указателя в число
Не надо гипотез. В стандарте все описано. И неявные преобразования, и коммуникативность сложения. Операция разыменования указателя ('*') определена только для указателей, значит результатом суммы должен быть указатель. Сумма дает указатель только если одно из слагаемых указатель, а второе - целое число. Порядок слагаемых не важен. Все описано и ничего выдумывать не нужно.
Цитата
One of the expressions shall have type ‘‘pointer to object type’’, the other expression shall have integer type, and the result has type ‘‘type’’.
Все. "одно из выражений" и "другое выражение". Где из них какое - не сказано и значения не имеет, что следует из отцитированного выше определения (definition). И массив не нужен, нужен указатель.

Цитата(GetSmart @ Jan 25 2016, 05:21) *
У понятия взятия элемента массива
Нет такого понятия. Есть доступ по индексу.
Цитата(GetSmart @ Jan 25 2016, 05:21) *
В том же стандарте Си наверняка в разделе объявлений переменных (конкретно массивов) указано (например неявно), что нет никакой симметрии и имя массива всегда вне [].
Во-первых давайте без "наверняка". Найдите и покажите. Я за вас искать не буду. "Чтение документации из интернета вслух - 100 евро в час". Во-вторых, объявление массива и операция доступа по индексу - совершенно разные и никак не связанные между собой вещи.

На этом заканчиваю. Не имею желания опровергать ваши фантазии. Читайте стандарт самостоятельно, там есть ответы на все ваши вопросы.

Цитата(GetSmart @ Jan 25 2016, 05:21) *
Прямо в Си-стандарте, а не в стандарте "соседнего" языка.
Это вообще к чему?
GetSmart
Цитата(Сергей Борщ @ Jan 25 2016, 11:43) *
definition = определение. То есть операция [] определяется и работает именно так, только так и никак иначе.

Я так и понял. Весь остальной мой абзац корректен.

Цитата(Сергей Борщ @ Jan 25 2016, 11:43) *
Это вообще к чему?

Предполагал некоторую связь с Си++. Например термин subscript не очень ясен. Слабо похож на русский "взятие элемента массива" или даже "индексирование".

Обобщая правила в Си, относящиеся к агрегатным типам, всегда операция взятия субэлемента сложного типа является асимметричной к типу операндов.

Плюсование/минусование указателя удобно в языке, но происходит в особом порядке. Компилятор этот случай детектит специально. В этом случае у операций +/- могла быть разрешена симметрия, по желанию разработчиков, из-за симметрии с числовыми операндами. Но можно было бы и жёстко задать: указатель слева, числа справа.
SSerge
Кабы авторы языка С в своё время были так же искусны во всех этих теориях то у них получился бы ещё один PL/1.
А так "маємо, що маємо".
Сергей Борщ
Цитата(GetSmart @ Jan 25 2016, 09:56) *
Предполагал некоторую связь с Си++.
В заголовке темы явно указан Си. Далее, вы сами писали о "чистом как слеза Си" и я вам отвечал именно о нем же, даже специально дважды повторил предлженное вами название.
Цитата(GetSmart @ Jan 25 2016, 09:56) *
Например термин subscript не очень ясен.
translate.google.com, технические словари вам в помощь.

Цитата(GetSmart @ Jan 25 2016, 09:56) *
Обобщая правила в Си,
Которых вы не читали. Выше добавил в сообщение еще одну цитату из стандарта.
GetSmart
Цитата(Сергей Борщ @ Jan 25 2016, 12:08) *
Которых вы не читали. Выше добавил в сообщение еще одну цитату из стандарта.

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

Гугл-транслейт может завести в такие дебри, что пожалеешь, что запустил sm.gif Пользуюсь бумажным словарём. Хорошим и толстым.
Сергей Борщ
Цитата(GetSmart @ Jan 25 2016, 10:16) *
По конкретной теме обсуждения аргументирую конструктивно.
"возможно", "наверняка", "предполагал" - очень конструктивно, ага.
Цитата(GetSmart @ Jan 25 2016, 10:16) *
Читать весь стандарт нет смысла
Поиск по тексту работает.
Цитата(GetSmart @ Jan 25 2016, 10:16) *
Возразите, если есть чем.
Ага, то есть языка не знаете вы, а возражать должен я? Нет уж, спасибо.
GetSmart
Цитата(Сергей Борщ @ Jan 25 2016, 12:54) *
"возможно", "наверняка", "предполагал" - очень конструктивно, ага.

Цитата(Сергей Борщ @ Jan 25 2016, 11:43) *
Нет такого понятия. Есть доступ по индексу.

То есть понятие массива есть. Понятие элемента массива тоже есть. А понятие взятия элемента - нет sm.gif
Оно есть даже если о нём прямо не говорится в стандарте. Оно может быть объединено/обобщено в новый термин, если он описывает более общий оператор. Этот оператор, кстати, на массивы, указатели на массив и указатели на другой непустой тип действует по-разному. И при таком раскладе обобщённый термин может ввести в заблуждение, рассуждая и корректности терминологии вообще.

Цитата
A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object.

Что-то здесь не так.
"Пост-выражение, идущее после выражения в квадратных скобках есть (термин - непонятные два слова) элемента массива".
Не видел такой конструкции в текстах.

Вряд ли автор хотел сказать, что "in square brackets" должно относиться к "postfix expression".
Если так, то это выражение не относится к взятию элемента массива. И не относится к взятию элемента по индексу, применённому к указателю на не массив.
Сергей Борщ
Цитата(GetSmart @ Jan 25 2016, 12:01) *
"Пост-выражение, идущее после выражения в квадратных скобках есть"
Постфиксное выражение, за которым следует выражение в квадратных скобках, является индексным обращением к элементу массива. "Обращением к элементу", а не "взятием элемента".

Код
char Array[] = "abcdef';
char * Pointer = Array;
int Index = 5;

// все эти выражения эквивалентны
display(Array[Index]);     // неявное преобразование Array к (char *)&Array[0]
display(Pointer[Index]);
display(Index[Pointer]);
display(*(Index + Pointer));
display(*(pointer + Index));
GetSmart
Цитата(Сергей Борщ @ Jan 25 2016, 14:34) *
Постфиксное выражение, за которым следует выражение в квадратных скобках, является индексным обращением к элементу массива.

Постфиксным выражением не может быть имя главного объекта, которое указывается первым левым идентификатором/именем. Можно контр-пример?

Цитата(Сергей Борщ @ Jan 25 2016, 14:34) *
"Обращением к элементу", а не "взятием элемента".

Напомнило "побочное действие присваивания есть присваивание".
В чём разница? В употреблённых мной контекстах. Если напишу так "Обобщая правила в Си, относящиеся к агрегатным типам, всегда операция обращения к его субэлементу является асимметричной к типу операндов."

Это понятие обобщает как минимум два более конкретных понятия: взятие адреса элемента и взятие содержимого элемента. Но в каких-то контекстах это обобщение корректно.

Цитата
Во-вторых, объявление массива и операция доступа по индексу - совершенно разные и никак не связанные между собой вещи.

Это утверждение неверно. В обоих случаях есть (будет) объект массив и число (размер или индекс). Оба ключевых признака в тексте на месте. И их позиции относительно оператора [] должны быть одинаковы, если нет весомых оснований отходить от этого. Та выделенная формулировка в цитате необоснованно навязывает допустимости варианта "индекс наизнанку" с аналогией со сложением, хотя сложение с указателем есть особый случай сложения. Если это желание разработчика, то это его личное дело. А если есть глубокие причины такого навязывания, то они должны были быть обозначены.
CrimsonPig
Цитата(GetSmart @ Jan 25 2016, 10:50) *
Постфиксным выражением не может быть имя главного объекта, которое указывается первым левым идентификатором/именем.


Ах! Поэзия! Посильнее "Фауста" Гете будет !

А вот что скажут теоретики программирования, пока, правда, не освоившие стандарт языка Ц на такое использование массивов ?

CODE
static char Foo1(uint32 aIdx)
{
return "abcdefghijkl"[aIdx];
}

static char Foo2(uint32 aIdx)
{
return aIdx["abcdefghijkl"];
}


... Это вам не про монадические типы рассуждать... sm.gif
GetSmart
Нашёл такую формулировку
Цитата
A postfix expression (operand followed by the operator) followed by an expression in square brackets [ ] is a subscripted designation of the array element .The definition of the array subscript operator [ ] is that if a is an array and i is an integer then a[i] =*(a+i).

В контексте которой есть определение postfix operator. Это индексирование [], передача параметров в функцию, ++ и другие. Соответственно postfix expression означает этот оператор без аргументов, с одним или списком аргументов. Естественно, postfix expression может быть только в комбинации с postfix operator, который применим только к допускающему его объекту слева от postfix-выражения.

В этом определении нет разрешения "индекса наизнанку" (в конце определения). Но понять смысл первого предложения невозможно. expression in square brackets [ ] и есть частный случай постфикс-выражения. В определении отсутствует главный объект.

Цитата
An operator is called a Postfix Operator when the operator follows the operand. Postfix Operators may operate on either one or two operators. There are five postfix operators in C:-
1. Array subscripts
2. Function Call
3. Structure and Union Members
4. Postfix Increment and Decrement Operators
5. Compound Literals


Цитата(CrimsonPig @ Jan 25 2016, 15:47) *
... Это вам не про монадические типы рассуждать... sm.gif

Ключевое слово (return и прочие) не являются именем.

В Си имена совпадающие с ключевыми словами запрещены.
Сергей Борщ
Цитата(CrimsonPig @ Jan 25 2016, 13:47) *
А вот что скажут теоретики программирования
Если бы некоторые писатели еще и читали предыдущие сообщения, они бы увидели, что именно эти примеры мы и пытались обсуждать.
GetSmart
Цитата(Сергей Борщ @ Jan 25 2016, 16:21) *
Если бы некоторые писатели еще и читали предыдущие сообщения, они бы увидели, что именно эти примеры мы и пытались обсуждать.

Цитата
Постфиксное выражение, за которым следует выражение в квадратных скобках, является индексным обращением к элементу массива. "Обращением к элементу", а не "взятием элемента".

x = array[index];

Что здесь постфиксное выражение? И какое слово в том определении переводится как обращение? "Указание" на элемент, возможно есть.
Сергей Борщ
Цитата(GetSmart @ Jan 25 2016, 14:19) *
В этом определении нет разрешения "индекса наизнанку" (в конце определения).
А никто и не говорит, что можно писать [index]Array.
Цитата(GetSmart @ Jan 25 2016, 14:19) *
Но понять смысл первого предложения невозможно. expression in square brackets [ ] и есть частный случай постфикс-выражения. В определении отсутствует главный объект.
Что-то вас конкретно клинит. Возьмем для простоты Array[index]. Здесь "Array" - postfix expression, (выражение, к которому может быть применен постфиксный оператор). "[]" - это postfix operator. index - expression in square brackets.

"Постфиксое выражение (Array) (операнд, за которым следует посфиксный оператор ([])), за которым следует выражение в квадратных скобках ([index]), является индексным обращением к элементу массива. Определение оператора индексного доступа [] таково, что если "a" есть массив и "i" есть целое число, то a[i] тождественно *(a+i)". Вот полный дословный перевод вашей цитаты.
Я не знаю, откуда вы ее взяли, я приводил цитату из стандарта ("Это документ между прочим!" голосом Мягкова из "Иронии судьбы"). В стандарте сказано "определение оператора индексного доступа таково, что E1[E2] идентично (*((E1)+(E2)))". Исходя из этого определения в операторе индексного доступа можно перед скобками указывать индекс, а в скобках указывать выражение, неявно приводимое к указателю. Можно, потому что правила языка такое допускают - целое число является постфиксным выражением, а для указателя определена операция сложения с первым аргументом и результат этого сложения имеет тип указателя. И реализация для обоих вариантов Array[index] и index[Array] исходя из определения получается идентичная с точностью до порядка слагаемых.

Цитата(GetSmart @ Jan 25 2016, 14:40) *
И какое слово в том определении переводится как обращение? "Указание" на элемент, возможно есть.
designation - указание, цель. Хорошо, пусть будет указание, что, по сути, и есть обращение.

В объявлении массива квадратные скобки являются частью определения, а не оператором индексного доступа, поэтому ваши попытки приплести сюда объявление массива бессмысленны.
GetSmart
Цитата(Сергей Борщ @ Jan 25 2016, 16:21) *
Если бы некоторые писатели еще и читали предыдущие сообщения, они бы увидели, что именно эти примеры мы и пытались обсуждать.

Общими усилиями удивляемся стандарту. То, что кривыми определениями там разрешена абракатабра. На счёт индексации строки я ошибся, т.к. строка в кавычках это особый тип выражения, а остальные замечания вполне законны.

Цитата(Сергей Борщ @ Jan 25 2016, 16:46) *
Что-то вас конкретно клинит. Возьмем для простоты Array[index]. Здесь "Array" - postfix expression, (выражение, к которому может быть применен постфиксный оператор). "[]" - это postfix operator. index - expression in square brackets.

Чтобы называть Array постфиксным выражением нужно ещё дав определение префиксному выражению и основному (точке отсчёта). Постфиксное выражение вообще-то всегда идёт за главным. Где здесь главное?

При такой фривольной интерпретации понятий, явно конфликтующей с общеупотребляемой терминологией должны быть обозначены причины.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.