Итерация по вектору членов Stucts с указателями и смещениями. Часть 2 - PullRequest
0 голосов
/ 31 января 2019

Итак, это часть 2 вопроса, который я задал и получил ответ вчера.Итак, сегодня я возвращаюсь с частью 2. Я не уверен, должно ли это быть где-то еще, так что, если модератор хочет переместить это, не стесняйтесь.

Так что я не собираюсь повторно представлять мою проблему здесь,поэтому, пожалуйста, прочитайте часть 1 Итерация по вектору членов stucts с указателями и смещениями

Итак, я нашел решение этой проблемы, поэтому позвольте мне опубликовать измененный фрагмент кода, которыйпредставляет решение, к которому я иду,

#include <iostream>
#include <vector>

// knows nothing about foo
class Readfoo
{ 
    private:
    int offSetSize;
    char* pchar;

    public:
    void SetPoint(double* apstartDouble, int aoffSetSize)  
    {
        offSetSize = aoffSetSize;
        pchar = static_cast<char*> (static_cast<void*>(apstartDouble));
    };

    const double& printfoo(int aioffset) const
    {
       return *(static_cast<double*> (static_cast<void*>(pchar + aioffset*offSetSize)));
    };
};

// knows nothing about readFoo
struct foo
{ 
    int a[5];
    double b[10];
};

int main() 
{
    // populate some data (choose b [2] or other random entry.).
    std::vector<foo> bar(10);
    for(int ii = 0; ii < bar.size(); ii++) 
        bar[ii].b[2] = ii;

    // access b[2] for each foo using an offset.
    Readfoo newReadfoo;
    newReadfoo.SetPoint(&(bar[0].b[2]), sizeof(foo)/sizeof(char));
    for(int ii = 0; ii < bar.size(); ii++)
        std::cout<<"\n"<<newReadfoo.printfoo(ii);

    return 0; 
}

Это, на мой взгляд, законно, я полагаю, это то, о чем я спрашиваю.По сути, теперь я, по сути, преобразую свою «интерпретацию» структуры foo и векторного бара (массива foos) в единый массив байтов или символов.

Т.е. в этой интерпретации структура данных представляет собой единый массив символов с размером foo и размером бара.Когда я повторяю это с целочисленным типом, я по сути перехожу к некоторому гипотетическому символу char (пункт 4.2 в ответе к части 1).Затем функция printfoo объединяет следующие 8 байтов, чтобы сформировать двойной код для возврата.

Так допустимо ли это, кроме выхода за пределы векторов стержней, есть ли какая-то причина, почему это не сработает (я проверил это, и оно еще не получилось)? *

1 Ответ

0 голосов
/ 31 января 2019

Так это законно ...

Нет, это не так.

В следующем выражении:

pchar + aioffset*offSetSize

вы манипулируете pchar, как если бы это был указатель на массив char, которым он не является (это указатель на массив double).И это неопределенное поведение:

[expr.add]/6

Для сложения или вычитания, если выражения P или Q имеют тип «указатель на cv T ”, где T и тип элемента массива не похожи, поведение не определено.[Примечание: В частности, указатель на базовый класс не может использоваться для арифметики указателей, когда массив содержит объекты типа производного класса.- конец примечания]

В вашем случае P равен pchar и имеет указатель типа на char, но элемент массива, на который он указывает, является double.


... и кроме выхода за пределы векторов стержней, есть ли какая-то причина, по которой это не сработает (я проверил это, и оно еще не вышло.)?

Да: Допускает ли стандарт C ++ неинициализированный bool для сбоя программы?


Чтобы пойти дальше: манипулирование указателем в C ++ - это красный флаг.Манипулирование указателями в C ++ - это темная магия, которая сожжет вашу душу и поглотит вашу собаку.C ++ предлагает множество инструментов для написания универсального кода.Мой совет: спросите о том, чего вы пытаетесь достичь, а не о своем попытке решения.Вы многому научитесь.

...