Здравствуйте, kov_serg, Вы писали:
_>constexpr int c3=(char*)1-(char*)0;
Насколько я понимаю, тут фактически reinterpret_cast.
The following solution:
class C {
public:
static constexpr const void* noop = reinterpret_cast<const void*>(0x1);
};
Although, it compiles and works fine in GCC isn't valid C++ (e.g., it doesn't compile with either clang or VC++2013) because according to the standard § 5.19/2 Constant Expressions [expr.const] the result of a reinterpret_cast can't be a constant expression.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, kov_serg, Вы писали:
_>>constexpr int c3=(char*)1-(char*)0;
PD>Насколько я понимаю, тут фактически reinterpret_cast.
PD>
PD>The following solution:
PD>class C {
PD>public:
PD> static constexpr const void* noop = reinterpret_cast<const void*>(0x1);
PD>};
PD>Although, it compiles and works fine in GCC isn't valid C++ (e.g., it doesn't compile with either clang or VC++2013) because according to the standard § 5.19/2 Constant Expressions [expr.const] the result of a reinterpret_cast can't be a constant expression.
Здравствуйте, kov_serg, Вы писали:
_>Это понятно, что сделано максимально через жопу, но в чем сакральный смысл так делать? Почему 1 не константа?
1 — константа, а вот преобразование типа не может быть выполнено в compile-time. В общем случае такое преобразование для указателей даже не гарантирует , что численное значение не изменится.
Здравствуйте, kov_serg, Вы писали:
_>Почему 2 и 3 строчки не константы ? _>
_>const int c1=(char*)1-(char*)0;
_>enum { c2=(char*)1-(char*)0 };
_>constexpr int c3=(char*)1-(char*)0;
_>
Я не знаю насчёт констант, но если я правильно помню, то все три выражения — это неопределённое поведение, так как разницу между указателями можно брать, только если указуемое принадлежат одному объекту или один (или оба указателя) указывает на следующий за объектом адрес.
Я затрудняюсь с ответом на вопрос: есть ли гарантия, что следующие указатели будут равны?:
Здравствуйте, B0FEE664, Вы писали:
BFE>но склоняюсь к ответу, что гарантии равенства по стандарту нет (implementation defined ЕМНИП).
Арифметика с char* разрешена. Так в чем проблема?
(char*)(a+b)-(char*)a = b или не очень?
BFE>Так что — да, для меня это какой-то дурацкий вопрос.
Все ответы на которые не удобно отвечать в C++ принято помечать как UB и от&$итесь
1. стандарт всегда прав
2. если стандарт не прав смотри путкт 1
Здравствуйте, kov_serg, Вы писали:
BFE>>но склоняюсь к ответу, что гарантии равенства по стандарту нет (implementation defined ЕМНИП). _>Арифметика с char* разрешена.
Только в пределах одного объекта.
_>Так в чем проблема?
ЕМНИП:
Нигде не сказано, что память плоская.
Нигде не сказано, что память линейная.
_>(char*)(a+b)-(char*)a = b или не очень?
Если указатель из себя представляет сегмент и смещение в нём, то как тогда?
BFE>>Так что — да, для меня это какой-то дурацкий вопрос. _>Все ответы на которые не удобно отвечать в C++ принято помечать как UB и от&$итесь _>
_>1. стандарт всегда прав
_>2. если стандарт не прав смотри путкт 1
Либо свобода и никакой конкретности, либо определённость и никакой свободы. Вы за свободу или как?
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, kov_serg, Вы писали:
BFE>>>но склоняюсь к ответу, что гарантии равенства по стандарту нет (implementation defined ЕМНИП). _>>Арифметика с char* разрешена. BFE>Только в пределах одного объекта.
А с чего вы взяли что это не впределах одного объекта.
_>>Так в чем проблема? BFE>ЕМНИП: BFE>Нигде не сказано, что память плоская. BFE>Нигде не сказано, что память линейная.
Точно кругом черные дыры искривляющие пространство память.
Так и как же работает https://en.cppreference.com/w/cpp/memory/addressof ?
_>>(char*)(a+b)-(char*)a = b или не очень? BFE>Если указатель из себя представляет сегмент и смещение в нём, то как тогда?
Оно даже с сегментами работает если впределах одного сегмента.
BFE>Либо свобода и никакой конкретности, либо определённость и никакой свободы. Вы за свободу или как?
Никаких крайностей только разумный баланс.
Здравствуйте, kov_serg, Вы писали:
_>Почему 2 и 3 строчки не константы ? _>
_>const int c1=(char*)1-(char*)0;
_>enum { c2=(char*)1-(char*)0 };
_>constexpr int c3=(char*)1-(char*)0;
_>
Потому что это всё — не константы времени компиляции?
Адресная арифметика определена только в пределах одного массива.
За его пределами — поведение как минимум, не специфицировано. (А точнее, это UB, на которое все закрывают глаза).
Даже вот так — нельзя
char x;
char y;
constexpr int d = &y - &x;
потому что разность адресов независимых объектов выяснится только на стадии линковки.
А вот так — можно
char x[] = "12345";
constexpr int d = &x[3] - &x[1];
потому что где бы ни был размещён массив, но смещения элементов друг относительно друга там известны сразу.
А вот так — gcc считает, что можно, а clang — что нельзя
struct foo {
char x;
int y;
char z;
};
foo f;
constexpr int d = &f.z - &f.x;
И я, пожалуй, соглашусь с clang: потому что в общем случае можно нахимичить с выравниванием, и для типов, чей sizeof не равен 1, адресная арифметика окажется дробной.
Надо покурить стандарт, где должно быть сказано, что при наличии таких хаков (а тем более, реинтерпретов (char*)1) программа становится ill-formed, no diagnostic required.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, kov_serg, Вы писали:
_>>Так и как же работает https://en.cppreference.com/w/cpp/memory/addressof ?
К>Он вообще к адресной арифметике отношения не имеет. К>addressof — это хак против перегрузки оператора &.
В C++ так принято не длелать еднообразно, а выполнять решения простых задач с помощью хаков.
Так ведь указатель на член -- это же не смещение. Т.е. смещение для одного и того же члена может быть разным в зависимости от объекта, к которому затем этот указатель применяется:
#include <iostream>
struct A {
int m_a{};
};
struct B : public A {
int m_b{};
};
struct C {
int m_c{};
};
struct D : C, A {
int m_d{};
};
int main()
{
using FieldPtr = int A::*;
B b;
b.m_a = 1;
D d;
d.m_a = 2;
FieldPtr p1 = &A::m_a;
std::cout << "B: " << b.*p1 << ", offsetof: " << offsetof(B, m_a) << std::endl;
std::cout << "D: " << d.*p1 << ", offsetof: " << offsetof(D, m_a) << std::endl;
}
Здравствуйте, so5team, Вы писали:
S>Так ведь указатель на член -- это же не смещение. Т.е. смещение для одного и того же члена может быть разным в зависимости от объекта, к которому затем этот указатель применяется:
Я немного про другое. Указатель на поле перевести в смещение. Что бы можно было оперировать идентификатором поля (числом), а не этим костылём под название указатель на член класса.
Здравствуйте, kov_serg, Вы писали:
BFE>>>>но склоняюсь к ответу, что гарантии равенства по стандарту нет (implementation defined ЕМНИП). _>>>Арифметика с char* разрешена. BFE>>Только в пределах одного объекта. _>А с чего вы взяли что это не впределах одного объекта.
Объект расположенный по адресу 0?
_>Точно кругом черные дыры искривляющие пространство память.
И вообще, бывает что адрес — IPv4
_>Так и как же работает https://en.cppreference.com/w/cpp/memory/addressof ?
Действительно, как же он работает? Погодите..., а может он берёт адрес объекта? Да — не, быть не может!
_>>>(char*)(a+b)-(char*)a = b или не очень? BFE>>Если указатель из себя представляет сегмент и смещение в нём, то как тогда? _>Оно даже с сегментами работает если впределах одного сегмента.
если.