Re[7]: (1[&array]-&array[0]) -- UB or not UB?
От: uzhas Ниоткуда  
Дата: 06.02.14 08:17
Оценка:
Здравствуйте, XuMuK, Вы писали:

XMK>оффтоп:


еще немного оффтопа : http://www.rsdn.ru/forum/cpp/4831841.flat
Автор: sts
Дата: 26.07.12
Re[6]: (1[&array]-&array[0]) -- UB or not UB?
От: Abyx Россия  
Дата: 06.02.14 08:31
Оценка: :)))
Здравствуйте, Erop, Вы писали:

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

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

скажи им что вместо & надо использовать std::addressof
In Zen We Trust
Re[6]: (1[&array]-&array[0]) -- UB or not UB?
От: Evgeny.Panasyuk Россия  
Дата: 06.02.14 08:41
Оценка: 10 (1)
Здравствуйте, 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] -- разыменование.


Тоже так считаю.
Re[7]: (1[&array]-&array[0]) -- UB or not UB?
От: Erop Россия  
Дата: 06.02.14 09:17
Оценка: +1
Здравствуйте, XuMuK, Вы писали:

XMK>оффтоп:

XMK>а чем такой вариант принципиально лучше шаблона jazzer'a или стандартного sizeof(array) / sizeof(*array) ?

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

A>скажи им что вместо & надо использовать std::addressof

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

Идея прикольная, но больно уж ошибкоопасная.

Классика жанра: вместо array подсунуть указатель на первый элемент.
В случае с sizeof(p)/sizeof(*p) мы получим константу времени компиляции, которая принимает значения от 0 до 8 в зависимости от платформы и типа элементов.
В случае (&p)[1]-&(p[0]) — константа времени исполнения, зависящая от того, какой мусор валяется в памяти рядом с указателем.
Перекуём баги на фичи!
Re[8]: (1[&array]-&array[0]) -- UB or not UB?
От: Abyx Россия  
Дата: 06.02.14 09:41
Оценка: :)
Здравствуйте, Erop, Вы писали:

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


A>>скажи им что вместо & надо использовать std::addressof

E>Зачем?
E>В смысле зачем говорить?
затем что & в обобщенном коде использовать нельзя потому что он может быть перегружен.
In Zen We Trust
Re[4]: (1[&array]-&array[0]) -- UB or not UB?
От: k55 Ниоткуда  
Дата: 06.02.14 09:45
Оценка:
Здравствуйте, Erop, Вы писали:

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


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


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

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

Спасибо за код. Долго курил, но вопрос остался. А почему тут происходит разименование адреса?
По тойже причине что и
cout << array;

автоматом разименует на 0 элемент?
Если есть желание — найдется 1000 возможностей.
Если нет желания — найдется 1000 причин.
Re[5]: (1[&array]-&array[0]) -- UB or not UB?
От: Evgeny.Panasyuk Россия  
Дата: 06.02.14 10:01
Оценка: 12 (2)
Здравствуйте, 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.

Возможно что и не UB.
Re[9]: (1[&array]-&array[0]) -- UB or not UB?
От: night beast СССР  
Дата: 06.02.14 10:07
Оценка: -1
Здравствуйте, Abyx, Вы писали:

A>>>скажи им что вместо & надо использовать std::addressof

E>>Зачем?
E>>В смысле зачем говорить?

A>затем что & в обобщенном коде использовать нельзя потому что он может быть перегружен.


за такие фокусы (перегрузка &) по рукам надо бы давать.
Re[2]: (1[&array]-&array[0]) -- UB or not UB?
От: Vlad_SP  
Дата: 06.02.14 10:08
Оценка:
Здравствуйте, Кодт, Вы писали:

К>В случае с sizeof(p)/sizeof(*p) мы получим константу времени компиляции, которая принимает значения от 0 до 8 в зависимости от платформы и типа элементов.


Гмм. Почему "от 0" ? Поясни, плз.
(То есть, если p — просто указатель, это понятно. Но как будто в треде обсуждается случай, когда p — честный массив. Нет?)
Re[6]: (1[&array]-&array[0]) -- UB or not UB?
От: Evgeny.Panasyuk Россия  
Дата: 06.02.14 10:10
Оценка:
EP>Возможно что и не UB.

Для UB тут есть ещё и другая возможность, помимо разыменования.
Насколько легален следующий код:
int main()
{
    int x = 0;
    auto first = &x;
    auto last = first + 1; // legal?
    // use as range [first, last)
}
?
Re[7]: (1[&array]-&array[0]) -- UB or not UB?
От: Erop Россия  
Дата: 06.02.14 10:36
Оценка: +1
Здравствуйте, 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>
?


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

E>>В смысле зачем говорить?

A>затем что & в обобщенном коде использовать нельзя потому что он может быть перегружен.
Это ответ на вопрос "зачем использовать?", а не на мой...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: (1[&array]-&array[0]) -- UB or not UB?
От: Evgeny.Panasyuk Россия  
Дата: 06.02.14 10:52
Оценка:
E>Вообще скалярные переменные во всей адресной арифметике везде могут трактоваться как массивы из одного элемента. Есть такой отдельный пункт в стандарте.

А какой пункт? Может кто знает/найдёт.
Я помню искал — да видимо keyword'ы не те.
Re[9]: (1[&array]-&array[0]) -- UB or not UB?
От: Fuz  
Дата: 06.02.14 11:26
Оценка: 28 (2)
Здравствуйте, 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.

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

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


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


I>Получается

I>
I>int array[10];

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

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

I>Ммм, нигде ничего не разыменовываем, поэтому вроде как не UB, надо смотреть можно ли так указатели приводить.

Исправлюсь напоследок, правильный вариант.

int* tmp1 = *(&array + 1);//1[&array]
int* tmp2 = *(&array);//&array[0]
cout << (tmp2 - tmp1);
Re[3]: (1[&array]-&array[0]) -- UB or not UB?
От: Igore Россия  
Дата: 06.02.14 11:39
Оценка:
Здравствуйте, Erop, Вы писали:

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


I>>Не UB,

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


E>Спасибо за разъяснения. Я верно понял, что с твоей т. з. тут всё нормуль:
int f( int i)
E>{
E>    return 1[&i];
E>}


Неверное сравнение, переделаю твой пример
int f( int i)
{
    return *(&i + 1);
}
Re[4]: (1[&array]-&array[0]) -- UB or not UB?
От: Erop Россия  
Дата: 06.02.14 13:07
Оценка:
Здравствуйте, 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]
ЭКВИВАЛЕНТНЫ...

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

E>Здравствуйте, 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>>


E>AFAIK, в С, и в С++, если не намудрить с перегрузкой операторов, выражения
*(1 + &i)
и
1[&i]
ЭКВИВАЛЕНТНЫ...


E>Тем не менее, всё нормуль, да?..


Нет, не нормуль. Мне передача по значению не понравилась.
В этом коде есть проблемы?
int inc( int* i )
{
   return 1[i];
}

int main(int argc, char* argv[])
{
   int arr[] = { 1, 2, 3 };
   cout << inc( &0[arr] ) << inc( &1[arr] ) << endl;
   return 0;
}
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.