pass an array? (stock c++)

Started by
20 comments, last by cozzie 8 years, 6 months ago

I was able to get it to work in VS 2015 only through type casting.

This compiles:






foo((int *)arr,10,10);

A c-style cast might as well be a reinterpret_cast. Unless you can get by with a simple static_cast I would be highly suspect of any such code. (And this ignores the other problems with passing the array dimensions separately)

Unless you have a really good reason to avoid heap allocation, I would always recommend writing a wrapper around a single dimensional std::vector that provides a 2D interface.
Multidimensional array syntax is a nightmare in C and C++.

I don't think OP is doing that necessarily. They're looking for a way to pass an array of unknown size to a function. A pointer along with a length or stride is perfectly workable and efficient (though makes the interface prone to mistakes).

BTW, those mistakes are exactly the kind of thing lkmViper noted above that array_view is meant to fix, however I believe array_view only works on a single dimension -- I could be mistaken though.


array_view works on multi-dimensional arrays. It's even smart enough to deduce the dimensions for the array from the variable in op's code since the arrays are compile-time sized.
Advertisement

I was able to get it to work in VS 2015 only through type casting.

This compiles:





foo((int *)arr,10,10);


A c-style cast might as well be a reinterpret_cast. Unless you can get by with a simple static_cast I would be highly suspect of any such code. (And this ignores the other problems with passing the array dimensions separately)


Nothing about the original code sample was C++, so I figured, why not?

Because you should fix the underlying problem (the type in the function declaration), not cast away compiler errors.

Because you should fix the underlying problem (the type in the function declaration), not cast away compiler errors.


I'll grant you that, but the method I posted was valid for decades. I'm curious. How bad is casting, and why is it considered bad form/dangerous now? I get that doing something stupid like casting a float to a string in the hopes that you could print the float is dumb, but in this case, it is casing a pointer to a pointer.

I'll grant you that, but the method I posted was valid for decades. I'm curious. How bad is casting, and why is it considered bad form/dangerous now? I get that doing something stupid like casting a float to a string in the hopes that you could print the float is dumb, but in this case, it is casing a pointer to a pointer.

Well first, a c-style cast gives no indication as to what it's actually doing under the covers (and it's very hard to search for these kind of casts in code). For pointer to pointer, under the covers it'll actually end up doing either a static_cast or reinterpret_cast depending on what the two types are.

A static_cast is "safer" in that it requires the two pointer types to be related, and applies the correct pointer arithmetic as needed. A reinterpret_cast is "more dangerous" in that it converts from any type to another without requiring the types be related and without changing the numerical value. You're essentially losing any type safety, and so seeing a reinterpret_cast should call special attention to that piece of code. I think the only place I ever use it is when calling legacy C apis that take pointers as integers and such.

So at the very least, you may as well use c++ casts - and in this case a reinterpret_cast will call attention to the fact that you're doing something sketchy (although it is correct).

A c-style cast could bite you if you had code that relied on the compiler treating it as static_cast, say; and then you changed one of the types causing the cast to actually be like a reinterpret_cast. Now you might have unexpectedly different pointer values as a result (whereas if you had been using an actual static_cast, you'd now be alerted to the problem by a compile error). Can't think of a good example off-hand....

Nothing about the original code sample was C++, so I figured, why not?


Aside from all the reasons others posted, the OP specifically said "C++" in their post.

Good C++ practice generally avoids writing C when C++ has a better (and safer) alternative.

Essentially, it's the same reason we don't code in binary anymore. We have tools that not only make things easier, but which can check our work for us and prevent us from making mistakes without any loss of speed or storage, so why not use them?

In some cases using specific C++ features instead of the old C versions actually makes it easier for the compiler to optimize your code because your intentions are much clearer to the compiler. I.e. ranged-for loops can be better optimized than regular for loops because the compiler is allowed to make additional assumptions about how they operate and what kinds of operations are valid inside said loops.

while the vector version will be much safer, i believe the correct old school syntax should be:

void foo(int * a, int sizeX, int sizeY, int value)

{

a[sizeY*sizeof(int)+sizeX]=value;

}

void main()

{

int arr[10*10];

foo(arr,2,5,1);
}
you declared arr as a two dimensional array, but in foo, you try to address it as a one dimensional array.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Yes i want to be able to pass all my different arrays (typically 2-dimensions) to the function.

But I only know how to make the function work with 1-dimensional arrays (as it takes a pointer).

It works as intented for me now (albeigt it might be somewhat ugly)

Yes i want to be able to pass all my different arrays (typically 2-dimensions) to the function.

But I only know how to make the function work with 1-dimensional arrays (as it takes a pointer).

It works as intented for me now (albeigt it might be somewhat ugly)

Why use two dimensional arrays in the first place? You don't gain much, if anything, from using a multi-dimensional array.


Yes i want to be able to pass all my different arrays (typically 2-dimensions) to the function.

address resolution will depend on the dimensionality of the array.

1D:

int array[max_x];

array[x]=value;

2D:

int array[max_y][max_x]; or int array[max_y*max_x];

array[y*max_x+x]=value;

3D:

int array[max_z][max_y][max_x]; or int array[max_z*max_y*max_x];

array[z*max_y*max_x+y*max_x+x]=value; (i _think_ that's right, i prefer multi dimensional arrays to avoid such BS math junk)

and you'll need to know the size of the array to resolve the address. so you end up passing array, x, y, max_x, and max_y for both one and two dimensional arrays!

of course you can hard code max_x and max_y so you don't have to pass them, but we all know hard coded magic numbers are frowned upon. if you change your array size you break your code.

so you might as well have two methods, one for 2D arrays and one for 1D.

when you have an API like that, with 1d and 2d versions, studies show its better to do a 1d api and a 2d api, rather than an all-in-one 1d and 2d API. with the all in one API you end up passing data or flags you don't have to.

or better yet, why bother with setter methods at all when you can just do array[x][y]=value and get on with life? you might be over-engineering things. is there some reason why a simple assignment statement won't work?

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

This topic is closed to new replies.

Advertisement