简体   繁体   中英

C/C++ ISO compliant casting void ptr to multidimensional arrays

I have a function in C++ that looks like:

//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);
}


The two casts produce an error with little detail as to why.

 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)]}

If I am not mistaken, both lvalue type and the corresponding cast is similar. For future reference, should I have more than 2 dimensions, how can I add them? I'm still an amateur in pointer manipulation so this will help alot.

EDIT this does not produce any errors in 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);
      }
}

In Standard C++ the array bounds must be constant expressions. Both of your examples are ill-formed.

The difference in compiler behaviour you observe relates to a non-standard extension provided by your compiler that evidently treats the two cases different; consulting your compiler's documentation might be a way to proceed if you want to go further down that avenue.

Of course my advice would be to use standard constructs, then it will work on every compiler and the behaviour is well-documented.


The simplest solution to the requirement of "create a contiguous 2-D array with variable dimensions and pass by reference to a function" is actually to create a vector and bear with the minor inconvenience of using x + y*COLS instead of [x][y] for accessing it.

The code might look like (pseudocode):

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

with caller:

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

It would be possible to write a Matrix-like class that allows the [x][y] access syntax, eg see here or google for more examples.

You could make an accessor for using parentheses syntax, eg:

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

arr(3, 4) = 5;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM