通过指针访问数据(重新解释转换)vs。或 - >操作者

时间:2018-01-05 22:01:04

标签: c++ pointers disk pointer-arithmetic reinterpret-cast

使用reinterpret_cast通过指针地址访问数据的主要目的是什么。是否更快,如果是这样,究竟是怎么回事?

在程序下面,通过打印相同的结构数据。运算符和via指针(重新解释转换)。

#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;
}

3 个答案:

答案 0 :(得分:2)

不,不快。 (虽然这取决于你想要做什么)

稍微修改你的例子

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

说,'让我把这个对象视为一个原始的字节数组'。有很多理由想要这样做。他们中的许多人将通过读,写,发送,memcpy等方式复制内容。

您还可以看到反向

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

你有一个字节数组,你想把它当作一个结构(你刚读过你之前写过的东西。

请注意,这是一项高级技术,与填充,字节顺序等有很多陷阱。不是100级的事情

答案 1 :(得分:1)

你所拥有的东西是不可靠的,因为当你增加intPtr时,它会通过整数的大小(你告诉它指向的内容)在内存中前进。无法保证结构中的字段是整数大小的。当然,它们不是所有整数大小的项目,并且编译器可以在结构中的字段之间添加填充。增加指针并不会试图找到下一个实际上的位置,它只是指向它所指向的大小。这只适用于数组。

Reinterpret_cast主要告诉编译器让你做一些它知道不好的事情。比如尝试将结构视为数组。除非是你不应该做的事情,否则它不会加快速度。

答案 2 :(得分:1)

您只能通过所谓的指针访问权限访问第一个成员。这是允许的,因为vv.one根据[basic.compound] paragraph 4是指针可互换的:

  

如果出现以下情况,则两个对象a和b是指针可互换的

     
      
  • ...

  •   
  • 一个是标准布局类对象,另一个是该对象的第一个非静态数据成员,或者......

  •   
  • ...

  •   
     

如果两个对象是指针可互换的,那么它们具有相同的地址,并且可以通过reinterpret_­cast从指向另一个的指针获得一个指针。

但是,我能看到的唯一好处是,即使您不知道其名称,也可以访问该成员(例如,您的示例中为one)。

注意:我相信应该没有性能提升。否则,优化程序可以优化v.one的评估,就好像reinterpret_cast<int*>(&v)被评估而不是,因为他们知道它们在编译时是等效的

在示例中通过指针访问访问其他成员是未定义的行为。正如@TWBennet所说,一个原因是相邻成员之间可能存在填充。但是,即使没有填充,intptr++也只会获得pointer past-the-end,即使在同一地址也不会自动指向该成员。您可以在that question中查看详细信息。