Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Я уверен, Егор это и так знает. Видимо, весь вопрос в волшебном символе &, а точнее в его положении — в одном случае он задает адрес элемента массива, а в другом — адрес всего массива.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, Igore, Вы писали:
I>>Здравствуйте, Erop, Вы писали:
E>>>SUBJ
I>>Не UB, I>>1[array] == array[1], грубо говоря I>>1 + *pointer == *pointer + 1
R>Я уверен, Егор это и так знает. Видимо, весь вопрос в волшебном символе &, а точнее в его положении — в одном случае он задает адрес элемента массива, а в другом — адрес всего массива.
int array[146];
assert( (1[&array] - &array[0]) == 146 );
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, rg45, Вы писали:
R>Я уверен, Егор это и так знает. Видимо, весь вопрос в волшебном символе &, а точнее в его положении — в одном случае он задает адрес элемента массива, а в другом — адрес всего массива.
Именно так. Формально мы ка кбы разыменовываем указатель на место за массивом, но разыменовываем его только для того, что бы преобразовать к адресу нулевого элемента этого несуществующего массива, то есть, фактически,
(typeof(array[0])*)1[&array]
это получение указателя на конец массива.
Вопрос в том, валидно ли такое недоразыменование?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Спасибо за разъяснения. Я верно понял, что с твоей т. з. тут всё нормуль:
int f( int i)
{
return 1[&i];
}
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, rg45, Вы писали:
R>Я уверен, Егор это и так знает. Видимо, весь вопрос в волшебном символе &, а точнее в его положении — в одном случае он задает адрес элемента массива, а в другом — адрес всего массива.
А почему? Ведь &array == array == &array[0]?
И array[1] == 1[array].
Или для array[size] берётся не sizeof(array[0]), а sizeof(array[size])?
Пользуйся, пожалуйста, тэгами [c] тут код [/c]
I>Да уж, проверил
&array[1] != 1[&array]
, получается
Тут скобки не так стоят, как ты думаешь.
&array[1]
/*интерпретируется как */
&(array[1])
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, flаt, Вы писали:
F>А почему?
По грамматике и семантике языка
F>Ведь
&array == array == &array[0]
?
1) первое равенство вообще не имеет места быть,
2) второе просто использует неявное приведение типов, реально тип массива и указателя на нулевой элемент массива отличается, соответственно и результаты операция могут быть разными.
Кстати, печально, что-то, походу, тут только один коллега понял вопрос, но всё равно не знает ответа...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Именно так. Формально мы ка кбы разыменовываем указатель на место за массивом, но разыменовываем его только для того, что бы преобразовать к адресу нулевого элемента этого несуществующего массива, то есть, фактически,
(typeof(array[0])*)1[&array]
это получение указателя на конец массива. E>Вопрос в том, валидно ли такое недоразыменование?
имхо, нет. С указателем на место за массивом никаких проблем нет (это специально оговорено), а вот с его разыменованием — очевидно, есть. То, что он как-то дальше особенным способом используется, рояли не играет. Так что если тебе нужен просто указатель на место за массивом — используй арифметику указателей, с ней никаких проблем. Тем более что тебе доступен размер массива, так как он вшит в его тип (иначе бы твой код не работал вообще).
А зачем вообще это нужно? Какую задачу ты решаешь этим кодом?
Здравствуйте, jazzer, Вы писали:
J>А зачем вообще это нужно? Какую задачу ты решаешь этим кодом?
Встретил на ревью, юзали в качестве lengthof.
Написал, что нестандартно, опасно и не константа времени компиляции + UB.
Попросили аргументировать по UB, так как это а-та-та и депримирование вплоть до увольнения...
В целом я тоже считаю, что это UB, так как 1[&array] -- разыменование.
Но, с другой стороны, это же всего лишь ссылка, у которой потом берут адрес? Ссылку на конец массива получать ведь нельзя? Я верно понимаю?
Я как бы посмотрел стандарт, правда старый, но на вский случай решил проконсультроваться у коллег... Вопрос IMHO крайне казуистический всё-таки.
С другой стороны, просто интересно, насколько это UB реализуемо...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, flаt, Вы писали:
F>Почему? Операция взятия адреса от массива ничего не делает же?
Просто попробуй сравнить адреса
1 + &array
и
1 + array
и подумай делает она что-то или нет...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, flаt, Вы писали:
E>>1) первое равенство вообще не имеет места быть, F>Почему? Операция взятия адреса от массива ничего не делает же?
А ты про какой язык, кстати? Я имел в виду, что первого равенства нет в С++, там типы не приведутся...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, jazzer, Вы писали:
J>>А зачем вообще это нужно? Какую задачу ты решаешь этим кодом?
E>Встретил на ревью, юзали в качестве lengthof. E>Написал, что нестандартно, опасно и не константа времени компиляции + UB.
Согласен. Нафига заниматься жонглированием граблями в рантайме, когда можно пользоваться девайсами времени компиляции типа
(формально тут рантайм-функция, но так как она возвращает константу времени компиляции, любой вменяемый компилятор просто вставит константу; а в С++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. Им ничто не мешает отслеживать все разыменования и форматировать винчестер, если что не так
Здравствуйте, flаt, Вы писали:
F>А почему? Ведь &array == array == &array[0]?
Широко распространенное заблуждение. Почему-то людям кажется, что если массив неявно преобразуется к указателю, то адрес массива и сам массив — это одно и тоже Нет. Выражения &array и array имеют разные типы, не подлежащие даже сравнению.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, Erop, Вы писали:
E>Встретил на ревью, юзали в качестве lengthof. E>Написал, что нестандартно, опасно и не константа времени компиляции + UB. E>Попросили аргументировать по UB, так как это а-та-та и депримирование вплоть до увольнения...
скажи им что вместо & надо использовать std::addressof
Здравствуйте, Erop, Вы писали:
J>>А зачем вообще это нужно? Какую задачу ты решаешь этим кодом? E>Встретил на ревью, юзали в качестве lengthof. E>Написал, что нестандартно, опасно и не константа времени компиляции + UB.
#include <type_traits>
int main()
{
char array[1][11];
static_assert(std::is_same<decltype((1[&array[0]])), decltype((array[1]))>::value, "");
static_assert(&1[&array[0]] == &array[1], "");
array[1]; // line #10
array[1]-&array[0][0]; // line #11
1[&array[0]]-&array[0][0]; // line #13
1[&array[0]]-&array[0][0]; // line #14
}
clang++ -std=c++11 -O0 -Wall -Wno-unused-value -pedantic -pthread main.cpp && ./a.out
main.cpp:10:5: warning: array index 1 is past the end of the array (which contains 1 element) [-Warray-bounds]
array[1]; // line #10
^ ~
main.cpp:5:5: note: array 'array' declared here
char array[1][11];
^
main.cpp:11:5: warning: array index 1 is past the end of the array (which contains 1 element) [-Warray-bounds]
array[1]-&array[0][0]; // line #11
^ ~
main.cpp:5:5: note: array 'array' declared here
char array[1][11];
^
2 warnings generated.
Clang во втором случае warning не выдаёт, но я думаю это скорей всего недоработка.
Достаточно доказать ссылаясь на пункты ISO тождественное равенство array[1] и 1[&array[0]], чтобы заручится поддержкой Clang'а.
E>Попросили аргументировать по UB, так как это а-та-та и депримирование вплоть до увольнения...
Это Хотя молодцы
E>В целом я тоже считаю, что это UB, так как 1[&array] -- разыменование.
Здравствуйте, XuMuK, Вы писали:
XMK>оффтоп: XMK>а чем такой вариант принципиально лучше шаблона jazzer'a или стандартного sizeof(array) / sizeof(*array) ?
Кто бы знал...
IMHO, автор хотел выпендриться...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Abyx, Вы писали:
A>скажи им что вместо & надо использовать std::addressof
Зачем?
В смысле зачем говорить?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Классика жанра: вместо array подсунуть указатель на первый элемент.
В случае с sizeof(p)/sizeof(*p) мы получим константу времени компиляции, которая принимает значения от 0 до 8 в зависимости от платформы и типа элементов.
В случае (&p)[1]-&(p[0]) — константа времени исполнения, зависящая от того, какой мусор валяется в памяти рядом с указателем.
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, Abyx, Вы писали:
A>>скажи им что вместо & надо использовать std::addressof E>Зачем? E>В смысле зачем говорить?
затем что & в обобщенном коде использовать нельзя потому что он может быть перегружен.
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, rg45, Вы писали:
R>>Я уверен, Егор это и так знает. Видимо, весь вопрос в волшебном символе &, а точнее в его положении — в одном случае он задает адрес элемента массива, а в другом — адрес всего массива.
E>Именно так. Формально мы ка кбы разыменовываем указатель на место за массивом, но разыменовываем его только для того, что бы преобразовать к адресу нулевого элемента этого несуществующего массива, то есть, фактически,
(typeof(array[0])*)1[&array]
это получение указателя на конец массива. E>Вопрос в том, валидно ли такое недоразыменование?
Спасибо за код. Долго курил, но вопрос остался. А почему тут происходит разименование адреса?
По тойже причине что и
cout << array;
автоматом разименует на 0 элемент?
Если есть желание — найдется 1000 возможностей.
Если нет желания — найдется 1000 причин.
Здравствуйте, k55, Вы писали:
k55>Спасибо за код. Долго курил, но вопрос остался. А почему тут происходит разименование адреса?
Ещё со времён C, для массивов 1[x] тождественно равно *(1+x). ISO/IEC 9899:TC2:
6.5.2.1 Array subscripting
[...]
2 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))). [...]
Если нет специальных правил для &* (на подобие short-circuit evaluation) — то происходит dereferencing.
Хотя я нашёл вот такие пункты в ISO C:
6.5.3.2 Address and indirection operators
[...]
3. The unary & operator yields the address of its operand. If the operand has type ‘‘type’’, the result has type ‘‘pointer to type’’. If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue. Similarly, if the operand is the result of a [] operator, neither the & operator nor the unary * that is implied by the [] is evaluated and the result is as if the & operator were removed and the [] operator were changed to a + operator. Otherwise, the result is a pointer to the object or function designated by its operand.
4. The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.84)
[...]
84) Thus, &*E is equivalent to E (even if E is a null pointer), and &(E1[E2]) to ((E1)+(E2)). It is always true that if E is a function designator or an lvalue that is a valid operand of the unary & operator, *&E is a function designator or an lvalue equal to E. If *P is an lvalue and T is the name of an object pointer type, *(T)P is an lvalue that has a type compatible with that to which T points.
Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime.
Здравствуйте, Abyx, Вы писали:
A>>>скажи им что вместо & надо использовать std::addressof E>>Зачем? E>>В смысле зачем говорить?
A>затем что & в обобщенном коде использовать нельзя потому что он может быть перегружен.
за такие фокусы (перегрузка &) по рукам надо бы давать.
Здравствуйте, Кодт, Вы писали:
К>В случае с sizeof(p)/sizeof(*p) мы получим константу времени компиляции, которая принимает значения от 0 до 8 в зависимости от платформы и типа элементов.
Гмм. Почему "от 0" ? Поясни, плз.
(То есть, если p — просто указатель, это понятно. Но как будто в треде обсуждается случай, когда p — честный массив. Нет?)
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Насколько легален следующий код: EP>
EP>int main()
EP>{
EP> int x = 0;
EP> auto first = &x;
EP> auto last = first + 1; // legal?
EP> // use as range [first, last)
EP>}
EP>
?
В С++ легален. В С -- не смотрел, но скорее всего тоже легаелен.
Вообще скалярные переменные во всей адресной арифметике везде могут трактоваться как массивы из одного элемента. Есть такой отдельный пункт в стандарте.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Abyx, Вы писали:
E>>В смысле зачем говорить? A>затем что & в обобщенном коде использовать нельзя потому что он может быть перегружен.
Это ответ на вопрос "зачем использовать?", а не на мой...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
E>Вообще скалярные переменные во всей адресной арифметике везде могут трактоваться как массивы из одного элемента. Есть такой отдельный пункт в стандарте.
А какой пункт? Может кто знает/найдёт.
Я помню искал — да видимо keyword'ы не те.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
E>>Вообще скалярные переменные во всей адресной арифметике везде могут трактоваться как массивы из одного элемента. Есть такой отдельный пункт в стандарте.
EP>А какой пункт? Может кто знает/найдёт. EP>Я помню искал — да видимо keyword'ы не те.
5.7 (Additive operators)
...
4. For the purposes of these operators, a pointer to a nonarray object behaves the same as a pointer to the
first element of an array of length one with the type of the object as its element type.
Здравствуйте, Igore, Вы писали:
E>>Спасибо за разъяснения. Я верно понял, что с твоей т. з. тут всё нормуль:
int f( int i)
E>>{
E>> return 1[&i];
E>>}
I>Неверное сравнение, переделаю твой пример I>
I>int f( int i)
I>{
I> return *(&i + 1);
I>}
I>
AFAIK, в С, и в С++, если не намудрить с перегрузкой операторов, выражения
*(1 + &i)
и
1[&i]
ЭКВИВАЛЕНТНЫ...
Тем не менее, всё нормуль, да?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Igore, Вы писали:
I>Нет, не нормуль. Мне передача по значению не понравилась.
Дык в исходном примере array был автоматической переменной жеж, а не строкой в массиве...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, rg45, Вы писали:
R>Широко распространенное заблуждение. Почему-то людям кажется, что если массив неявно преобразуется к указателю, то адрес массива и сам массив — это одно и тоже Нет. Выражения &array и array имеют разные типы, не подлежащие даже сравнению.
Ну, в С вроде как типы разные, а сравнить всё равно можно...
Правда если там и там по +1 приписать, то уже не будет равенства даже в С...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском