C / C ++ ISO-совместимое приведение void ptr к многомерным массивам - PullRequest
0 голосов
/ 11 апреля 2020

У меня есть функция в C ++, которая выглядит следующим образом:

//ellipsis are irrelevant variables. Not variadic
lint find_max(const void* ptr, ... , const vector<lint> &nums, ...)
{
    const mm (*arr)[nums.size()] = (const mm (*)[nums.size()]) ptr;
    //or
    const mm (*arr1)[nums.size()] = reinterpret_cast<const mm (*)[nums.size()]>
                                      (ptr);
}


Два приведения приводят к ошибке с небольшой детализацией относительно того, почему.

 error: cannot convert ‘const mm (*)[(<anonymous> + 1)]’ {aka ‘const min_and_max (*)[(<anonymous> + 1)]’} to ‘const mm (*)[(<anonymous> + 1)]’ {aka ‘const min_and_max (*)[(<anonymous> + 1)]’} in initialization
   42 |   const mm (*arr)[nums.size()] = (const mm(*)[nums.size()])ptr;
      |                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                                  |
      |                                  const mm (*)[(<anonymous> + 1)] {aka const min_and_max (*)[(<anonymous> + 1)]}

Если я не ошибаюсь, тип lvalue и соответствующий приведенный тип одинаковы. Для дальнейшего использования, если я должен иметь более двух измерений, как я могу добавить их? Я все еще любитель манипулирования указателями, так что это очень поможет.

EDIT это не приводит к ошибкам в g ++:

typedef long long int lint;

lint pInf = ~((unsigned long long int)0) >> 1;
lint nInf = ~pInf;

typedef struct min_and_max
{
    lint min{pInf};
    lint max{nInf};
}mm;


const lint find_max(const void* ptr, int i, int j, const vector<lint> &nums, 
                    const vector<char> &ops)
{
    const int dim = nums.size();
    const mm (*arr)[dim] = reinterpret_cast<const mm (*)[dim]>
                                      (ptr);

    //algorithm which I haven't figured out yet.
    some_lint_value = arr[i][j].max + arr[i-232414][j+46846].min;

    return some_lint_value;
}

void caller(vector<lint> &nums, vector<char> &ops)
{
    mm arr[ops.size()][nums.size()]; //ISO variable size forbid warn

    for (int i = 1; i <= ops.size(); i++)
      {
         for (int j = 1; j <= nums.size(); j++)
           //looped logic for solving the max/min value for an expression problem
           arr[i][j].max = find_max(arr, i, j, nums, ops);
      }
}

1 Ответ

1 голос
/ 11 апреля 2020

В стандарте C ++ границы массивов должны быть константными выражениями. Оба ваших примера плохо сформированы.

Различие в поведении компилятора, которое вы наблюдаете, связано с нестандартным расширением, предоставляемым вашим компилятором, которое, очевидно, рассматривает два случая по-разному; обращение к документации вашего компилятора может быть способом продолжить, если вы хотите go продвинуться дальше по этому пути.

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


Самое простое решение требования "создать непрерывный двумерный массив с переменными размерами и передать по ссылке на функцию" на самом деле создать вектор и выдержать второстепенное неудобство использования x + y*COLS вместо [x][y] для доступа к нему.

Код может выглядеть (псевдокод):

lint find_max(vector<mm> &arr2, vector<lint> const& nums, ....otherstuff)
{
    mm& item_at_x_y = arr2[x + y * nums.size()];
}

с вызывающим абонентом:

void caller()
{
     vector<mm> arr2( nums.size() * ops.size() );
     // populate arr2...
     find_max(arr2, nums, ops...);
}

Можно было бы написать класс, подобный Matrix, который позволяет [x][y] синтаксис доступа, например, см. Здесь или другие примеры в Google.

Вы можете создать средство доступа для использования синтаксиса скобок, например:

auto arr = [&](size_t y, size_t x) { return arr2[x + y * nums.size()]; };

arr(3, 4) = 5;
...