Доступ к данным с помощью указателя (переинтерпретация приведения) и . или -› оператор

Какова основная цель доступа к данным через адрес указателя с использованием reinterpret_cast. Это быстрее, если да, то как именно?

Ниже приведена программа, которая печатает те же данные структуры через файлы . оператор и через указатель (переосмысление приведения).

#include <iostream>
using namespace std;

struct values{
    int one;
    int two;
    char three;
    int four;
};

int main()
{
    values v { 8, 5, 'k', 653};

    // access via . (or ->) operator
    cout << v.one << endl;
    cout << v.two << endl;
    cout << v.three << endl;
    cout << v.four << endl;


    //via pointer access - how can this be beneficial?
    values* vPtr = &v;
    int* intPtr = reinterpret_cast<int*>(vPtr);
    cout << *intPtr << endl;
    intPtr++;
    cout << *intPtr << endl;
    intPtr++;
    char* charPtr = reinterpret_cast<char*>(intPtr);
    cout << *charPtr << endl;
    charPtr += 4;
    int* intPtr2 = reinterpret_cast<int*>(charPtr);
    cout << *intPtr2<< endl;

    return 0;
}

person Levi    schedule 05.01.2018    source источник
comment
Это просто Неопределенное Поведение. Вы нарушаете правило Strict Aliasing. Также знайте, что вы никогда не должны обращаться с членами данных класса (даже если они тривиальны) как с массивом любого вида.   -  person WhiZTiM    schedule 06.01.2018
comment
Связано: stackoverflow. ком/вопросы/48031228/   -  person R Sahu    schedule 06.01.2018
comment
Нет, reinterpret_cast не сделает ваш код быстрее. Это просто директива компилятора о том, как обрабатывать последовательность байтов.   -  person StPiere    schedule 06.01.2018
comment
эта ссылка должна быть полезна, чтобы прояснить ваши сомнения. stackoverflow.com/questions/573294/when-to-use -reinterpret-cast   -  person Abhishek Ramamurthy    schedule 06.01.2018
comment
reinterpret_cast может быть медленнее   -  person MSalters    schedule 08.01.2018
comment
@WhiZTiM здесь нет строгого нарушения псевдонимов. Можно получить доступ к int объекту через int lvalue   -  person M.M    schedule 08.01.2018


Ответы (3)


Вы можете получить доступ только к первому участнику через так называемый доступ по указателю. Это разрешено, поскольку v и v.one являются взаимопреобразующими указателями в соответствии с [basic.compound ] параграф 4:

Два объекта a и b являются взаимопреобразуемыми указателями, если:

  • ...

  • один является объектом класса стандартного макета, а другой является первым нестатическим элементом данных этого объекта, или...

  • ...

Если два объекта являются взаимопреобразующими по указателю, то они имеют один и тот же адрес, и можно получить указатель на один из указателя на другой через reinterpret_­cast.

Однако единственное преимущество, которое я вижу, заключается в том, что вы можете получить доступ к элементу, даже если не знаете его имени (например, one в вашем примере).

Примечание. Я считаю, что не должно прироста производительности. В противном случае оптимизатор может оптимизировать оценку v.one, как если бы вместо этого оценивалась reinterpret_cast<int*>(&v), зная, что они эквивалентны во время компиляции.


Доступ к другим членам через доступ к указателю в вашем примере является неопределенным поведением. Как сказал @TWBennet, одна из причин заключается в том, что между соседними элементами могут быть отступы. Однако, даже если заполнение отсутствует, intptr++ получает только указатель, the-end, который не будет автоматически указывать на участника даже по тому же адресу. Вы можете увидеть подробности в этот вопрос.

person xskxzr    schedule 08.01.2018

Нет не быстрее. (Хотя это зависит от того, что именно вы хотите сделать)

Немного изменив ваш пример

char* charPtr = reinterpret_cast<char*>(&v);

говорит: «Позвольте мне рассматривать этот объект как необработанный массив байтов». Есть много причин, чтобы хотеть это сделать. Многие из них будут связаны с копированием через чтение, запись, отправку, memcpy и т. д.

вы также можете увидеть обратное

values *v = reinterpret_cast<values*>(buff);

Где у вас есть массив байтов, который вы хотите рассматривать как структуру (вы только что прочитали что-то, что вы написали ранее.

Обратите внимание, что это продвинутая техника со многими ловушками, связанными с заполнением, порядком байтов и т. Д. Не 100-уровневая вещь.

person pm100    schedule 05.01.2018

То, что у вас есть, ненадежно, потому что, когда вы увеличиваете intPtr, он продвигается по памяти на размер целого числа (это то, на что вы сказали ему указывать). Нет никакой гарантии, что поля в структуре разделены целочисленным размером. Конечно, это не все элементы целочисленного размера, и компилятор может добавлять отступы между полями в структуре. Увеличение указателя не пытается найти, где на самом деле находится следующая вещь, он просто идет по размеру того, на что он указывает. Который работает только с массивами.

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

person T W Bennet    schedule 08.01.2018