(1[&array]-&array[0]) -- UB or not UB?
От: Erop Россия  
Дата: 06.02.14 02:02
Оценка: 4 (1)
SUBJ
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: (1[&array]-&array[0]) -- UB or not UB?
От: Igore Россия  
Дата: 06.02.14 05:57
Оценка:
Здравствуйте, Erop, Вы писали:

E>SUBJ


Не UB,
1[array] == array[1], грубо говоря
1 + *pointer == *pointer + 1
Re[2]: (1[&array]-&array[0]) -- UB or not UB?
От: rg45 СССР  
Дата: 06.02.14 06:03
Оценка: +3
Здравствуйте, Igore, Вы писали:

I>Здравствуйте, Erop, Вы писали:


E>>SUBJ


I>Не UB,

I>1[array] == array[1], грубо говоря
I>1 + *pointer == *pointer + 1

Я уверен, Егор это и так знает. Видимо, весь вопрос в волшебном символе &, а точнее в его положении — в одном случае он задает адрес элемента массива, а в другом — адрес всего массива.
--
Справедливость выше закона. А человечность выше справедливости.
Re[3]: (1[&array]-&array[0]) -- UB or not UB?
От: Igore Россия  
Дата: 06.02.14 06:16
Оценка: -1
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, Igore, Вы писали:


I>>Здравствуйте, Erop, Вы писали:


E>>>SUBJ


I>>Не UB,

I>>1[array] == array[1], грубо говоря
I>>1 + *pointer == *pointer + 1

R>Я уверен, Егор это и так знает. Видимо, весь вопрос в волшебном символе &, а точнее в его положении — в одном случае он задает адрес элемента массива, а в другом — адрес всего массива.


Ну тогда распишу полностью

1[&array]-&array[0] == &array[1] — &array[0] == &array[0] + 1 — &array[0] == 1
Re[4]: (1[&array]-&array[0]) -- UB or not UB?
От: Erop Россия  
Дата: 06.02.14 06:22
Оценка: 1 (1)
Здравствуйте, Igore, Вы писали:

I>Ну тогда распишу полностью


I>
1[&array]-&array[0] == &array[1] - &array[0] == &array[0] + 1 - &array[0] == 1


Не, не так
int array[146];
assert( (1[&array] - &array[0]) == 146 );
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: (1[&array]-&array[0]) -- UB or not UB?
От: Erop Россия  
Дата: 06.02.14 06:26
Оценка:
Здравствуйте, rg45, Вы писали:

R>Я уверен, Егор это и так знает. Видимо, весь вопрос в волшебном символе &, а точнее в его положении — в одном случае он задает адрес элемента массива, а в другом — адрес всего массива.


Именно так. Формально мы ка кбы разыменовываем указатель на место за массивом, но разыменовываем его только для того, что бы преобразовать к адресу нулевого элемента этого несуществующего массива, то есть, фактически,
(typeof(array[0])*)1[&array]
это получение указателя на конец массива.
Вопрос в том, валидно ли такое недоразыменование?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: (1[&array]-&array[0]) -- UB or not UB?
От: Erop Россия  
Дата: 06.02.14 06:29
Оценка:
Здравствуйте, Igore, Вы писали:

I>Не UB,

I>
1[array] == array[1], грубо говоря 
I>1 + *pointer == *pointer + 1


Спасибо за разъяснения. Я верно понял, что с твоей т. з. тут всё нормуль:
int f( int i)
{
    return 1[&i];
}
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: (1[&array]-&array[0]) -- UB or not UB?
От: Igore Россия  
Дата: 06.02.14 06:32
Оценка: +1
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Igore, Вы писали:


I>>Ну тогда распишу полностью


I>>
1[&array]-&array[0] == &array[1] - &array[0] == &array[0] + 1 - &array[0] == 1


E>Не, не так

E>
E>int array[146];
E>assert( (1[&array] - &array[0]) == 146 );


Да уж, проверил &array[1] != 1[&array], получается
Re[3]: (1[&array]-&array[0]) -- UB or not UB?
От: flаt  
Дата: 06.02.14 06:39
Оценка:
Здравствуйте, rg45, Вы писали:

R>Я уверен, Егор это и так знает. Видимо, весь вопрос в волшебном символе &, а точнее в его положении — в одном случае он задает адрес элемента массива, а в другом — адрес всего массива.


А почему? Ведь &array == array == &array[0]?
И array[1] == 1[array].

Или для array[size] берётся не sizeof(array[0]), а sizeof(array[size])?
Re[6]: (1[&array]-&array[0]) -- UB or not UB?
От: Erop Россия  
Дата: 06.02.14 06:42
Оценка:
Здравствуйте, Igore, Вы писали:

Пользуйся, пожалуйста, тэгами [c] тут код [/c]

I>Да уж, проверил
&array[1] != 1[&array]
, получается


Тут скобки не так стоят, как ты думаешь.
&array[1] 
/*интерпретируется как */
&(array[1])
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: (1[&array]-&array[0]) -- UB or not UB?
От: Erop Россия  
Дата: 06.02.14 06:46
Оценка:
Здравствуйте, flаt, Вы писали:

F>А почему?

По грамматике и семантике языка

F>Ведь
&array == array == &array[0]
?


1) первое равенство вообще не имеет места быть,
2) второе просто использует неявное приведение типов, реально тип массива и указателя на нулевой элемент массива отличается, соответственно и результаты операция могут быть разными.

Кстати, печально, что-то, походу, тут только один коллега понял вопрос, но всё равно не знает ответа...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: (1[&array]-&array[0]) -- UB or not UB?
От: jazzer Россия Skype: enerjazzer
Дата: 06.02.14 06:46
Оценка: 10 (1)
Здравствуйте, Erop, Вы писали:

E>Именно так. Формально мы ка кбы разыменовываем указатель на место за массивом, но разыменовываем его только для того, что бы преобразовать к адресу нулевого элемента этого несуществующего массива, то есть, фактически,
(typeof(array[0])*)1[&array]
это получение указателя на конец массива.

E>Вопрос в том, валидно ли такое недоразыменование?

имхо, нет. С указателем на место за массивом никаких проблем нет (это специально оговорено), а вот с его разыменованием — очевидно, есть. То, что он как-то дальше особенным способом используется, рояли не играет. Так что если тебе нужен просто указатель на место за массивом — используй арифметику указателей, с ней никаких проблем. Тем более что тебе доступен размер массива, так как он вшит в его тип (иначе бы твой код не работал вообще).

А зачем вообще это нужно? Какую задачу ты решаешь этим кодом?
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: (1[&array]-&array[0]) -- UB or not UB?
От: flаt  
Дата: 06.02.14 06:52
Оценка:
Здравствуйте, Erop, Вы писали:

E>1) первое равенство вообще не имеет места быть,

Почему? Операция взятия адреса от массива ничего не делает же?
Re[5]: (1[&array]-&array[0]) -- UB or not UB?
От: Erop Россия  
Дата: 06.02.14 06:52
Оценка:
Здравствуйте, jazzer, Вы писали:

J>А зачем вообще это нужно? Какую задачу ты решаешь этим кодом?


Встретил на ревью, юзали в качестве lengthof.
Написал, что нестандартно, опасно и не константа времени компиляции + UB.
Попросили аргументировать по UB, так как это а-та-та и депримирование вплоть до увольнения...

В целом я тоже считаю, что это UB, так как 1[&array] -- разыменование.
Но, с другой стороны, это же всего лишь ссылка, у которой потом берут адрес? Ссылку на конец массива получать ведь нельзя? Я верно понимаю?
Я как бы посмотрел стандарт, правда старый, но на вский случай решил проконсультроваться у коллег... Вопрос IMHO крайне казуистический всё-таки.

С другой стороны, просто интересно, насколько это UB реализуемо...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: (1[&array]-&array[0]) -- UB or not UB?
От: Erop Россия  
Дата: 06.02.14 06:56
Оценка:
Здравствуйте, flаt, Вы писали:

F>Почему? Операция взятия адреса от массива ничего не делает же?

Просто попробуй сравнить адреса
 1 + &array
и
1 + array
и подумай делает она что-то или нет...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: (1[&array]-&array[0]) -- UB or not UB?
От: Erop Россия  
Дата: 06.02.14 07:00
Оценка:
Здравствуйте, flаt, Вы писали:

E>>1) первое равенство вообще не имеет места быть,

F>Почему? Операция взятия адреса от массива ничего не делает же?

А ты про какой язык, кстати? Я имел в виду, что первого равенства нет в С++, там типы не приведутся...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: (1[&array]-&array[0]) -- UB or not UB?
От: Igore Россия  
Дата: 06.02.14 07:24
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Igore, Вы писали:


E>Пользуйся, пожалуйста, тэгами [c] тут код [/c]


I>>Да уж, проверил
&array[1] != 1[&array]
, получается


Получается
int array[10];

int (*tmp1)[10] = &array + 1;
int *tmp2 = &array[0];

cout << ((int*)tmp1 - tmp2);

Ммм, нигде ничего не разыменовываем, поэтому вроде как не UB, надо смотреть можно ли так указатели приводить.
Re[6]: (1[&array]-&array[0]) -- UB or not UB?
От: jazzer Россия Skype: enerjazzer
Дата: 06.02.14 07:27
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, jazzer, Вы писали:


J>>А зачем вообще это нужно? Какую задачу ты решаешь этим кодом?


E>Встретил на ревью, юзали в качестве lengthof.

E>Написал, что нестандартно, опасно и не константа времени компиляции + UB.
Согласен. Нафига заниматься жонглированием граблями в рантайме, когда можно пользоваться девайсами времени компиляции типа
boost/std::extent< ArrayType >::value

или
template <typename T, std::size_t N>
  inline std::size_t countof( T (&arr)[N] ) { return N; }

(формально тут рантайм-функция, но так как она возвращает константу времени компиляции, любой вменяемый компилятор просто вставит константу; а в С++11 ее вообще constexpr можно объявить)

E>Попросили аргументировать по UB, так как это а-та-та и депримирование вплоть до увольнения...

как-то жестковато для простого UB, имхо

E>В целом я тоже считаю, что это UB, так как 1[&array] -- разыменование.

именно:

The expression E1[E2] is identical (by definition) to *((E1)+(E2))

а в статье про оператор разыменования сказано:

The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an
object type, or a pointer to a function type and the result is an lvalue referring to the object or function
to which the expression points.

стало быть, если нет никакого объекта, на который указывает выражение (E1)+(E2), то и поведение не определено.
Это даже не говоря о том, что у разыменованного "объекта" может оказаться свой веселый перегруженный оператор* (а не встроенный), который может вызвать форматирование винчестера и запуск ракет.

E>Но, с другой стороны, это же всего лишь ссылка, у которой потом берут адрес? Ссылку на конец массива получать ведь нельзя? Я верно понимаю?

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

E>Я как бы посмотрел стандарт, правда старый, но на вский случай решил проконсультроваться у коллег... Вопрос IMHO крайне казуистический всё-таки.

E>С другой стороны, просто интересно, насколько это UB реализуемо...

Очень легко. Надо просто помнить про существование интерпретаторов С++, типа cint или cling. Им ничто не мешает отслеживать все разыменования и форматировать винчестер, если что не так
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: (1[&array]-&array[0]) -- UB or not UB?
От: rg45 СССР  
Дата: 06.02.14 07:44
Оценка: 6 (1) +1
Здравствуйте, flаt, Вы писали:

F>А почему? Ведь &array == array == &array[0]?


Широко распространенное заблуждение. Почему-то людям кажется, что если массив неявно преобразуется к указателю, то адрес массива и сам массив — это одно и тоже Нет. Выражения &array и array имеют разные типы, не подлежащие даже сравнению.
--
Справедливость выше закона. А человечность выше справедливости.
Re[6]: (1[&array]-&array[0]) -- UB or not UB?
От: XuMuK Россия  
Дата: 06.02.14 07:57
Оценка:
Здравствуйте, Erop, Вы писали:

E>Встретил на ревью, юзали в качестве lengthof.


оффтоп:
а чем такой вариант принципиально лучше шаблона jazzer'a или стандартного sizeof(array) / sizeof(*array) ?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.