what is wrong with this array usage in c++? - c++

#include<iomanip>
using namespace std;
void displaySeats(bool taken[][]){
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 30;j++)
if (taken[i][j])
cout << '*';
else
cout << '#';
cout << '\n';
}
}
int main()
{
bool taken[15][30];
int rows, clm;
rows = 15;
clm = 30;
displaySeats(taken);
system("PAUSE");
}
it is giving me errors like
an array may not have elements of this type line 6
'void displaySeats(bool [][])': cannot convert argument 1 from 'bool [15][30]' to 'bool [][]' line 25
'taken': missing subscript line 6
but if i move the code from the function to the main it works perfectly fine.
I can have a array of type bool.
there is subscript.
i've tried passing through a pointer to the array (which arrays are anyway)
i've tried passing through an array of pointers
a 2d array of pointers
a pointer of an array of pointers.
scoured stack exchange and looks at other peoples code and i am doing it almost line for line.
does it not work with bools? because it doesn't work with ints either.

When expecting an array argument on a function you don't need to know how many elements it has, since you can index it freely. However, you need to know how big each element is, to know how many bytes to skip for each index, when indexing.
In this case your element is a bool[30] with size 30 bytes. You need to signify this on your function signature.
void displaySeats(bool taken[15][30]){ // array 15*30 bool
// OR
void displaySeats(bool taken[][30]){ // array with elements bool[30]
// OR
void displaySeats(bool (*taken)[30]){ // pointer to element(s) bool[30]
See below on how 2d arrays are structured in memory and this will make sense.

This is a big topic. You need to research how arrays really work in C++. But the short (and surprising) answer is that you cannot have an array as a parameter to a function in C++. This code void func(int a[]) is actually an alternative for the pointer code void func(int* a).
But this simple rule only works for one dimension. With two dimensions only the first dimension is turned into a pointer. So the equivalent for your case would be
void displaySeats(bool (*taken)[30]){
or
void displaySeats(bool taken[][30]){
or
void displaySeats(bool taken[15][30]){
But the important part is that in all cases taken is a pointer not an array.
Because arrays are so useless in C++ we prefer to use std::vector, which doesn't have the same limitations (and has many other advantages besides).

The taken array must have some size defined like so taken[15][30].
Also, you have to include <iostream> in order to use cout.

try specifying size of array, or use reference see here
#include<iomanip>
#include <iostream>
using namespace std;
// template <typename t>
void displaySeats(bool taken[][30]){
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 30;j++)
if (taken[i][j])
cout << '*';
else
cout << '#';
cout << '\n';
}
}
int main()
{
bool taken[15][30];
int rows, clm;
rows = 15;
clm = 30;
displaySeats(taken);
system("PAUSE");
}

As mentioned, bool taken[][] isn't valid. Only the left-most (outer) array extent may be left unspecified.
I prefer the longest form to be explicit and to take the argument by reference. Motivation: Taking it as a pointer would lead to a runtime problem if you happen to pass in a nullptr by mistake (unless you check if(taken==nullptr) return; in the function). With a reference, you'd get a compilation error instead so there's no need to check if it's a nullptr.
Also, make the function argument const since you're not making changes to the array in the display function.
constexpr size_t ROWS = 15;
constexpr size_t COLS = 30;
void displaySeats(const bool (&taken)[ROWS][COLS]) {
using std::cout;
for (size_t i = 0; i < ROWS; i++) {
for (size_t j = 0; j < COLS;j++)
if (taken[i][j])
cout << '*';
else
cout << '#';
cout << '\n';
}
}
You can then easily turn this into a function template to accept arbitrary 2D arrays of bool:
template<size_t ROWS, size_t COLS>
void displaySeats(const bool (&taken)[ROWS][COLS]) {
// same as above
}

If you start to study language rules, not their interpretation, you'll come to realization that neither C nor C++ document doesn't mention an array with multiple dimensions at all, not like FORTRAN or flavors of Basic. It speaks about just an array as a form of object.
Array is an object which has a continuous storage containing multiple objects of same type. Array is an object. Thus we may have an array of arrays. That's what bool taken[15][30] is. It can be read this way
bool (taken[15])[30]; //Array of 15 arrays of 30 bools each
While this line is correct
void foo(bool arg[]) // same as void foo(bool *arg) for all purposes
And this one gives compiler some information:
void foo(bool arg[30]) // sizeof(arg) would return size of array,
// not size of pointer type
This line is ill-formed.
void boo(bool arg[][]) //
It would suggest an unknown type of array elements (how big is the element of array?), which contradicts ideology of strongly-typed language.
Two correct styles can be mixed:
void foo(bool arg[][30]) // same as void foo(bool (*arg)[30])
Here the parameter of function is a pointer to an array of bools.
Functions in C or C++ never could take an array or return an array. The reason to that is that C (and subsequently, C++) by default can pass parameters and return results by value, which means loading those values into stack. Doing that to array would be ineffective because of stack possible limitations. There were also logical conundrums in syntax, where name of array decays to a pointer. Thus arrays supposed to be passed by their address, by a pointer and can be returned only by pointer as well.
But you can pass structures by value and you can return them as result, even if they contain arrays. C++ classes expands functionality of original aggregate type struct and std::array is an example of template for such aggregate.

Related

Is it possible to pass a 2D array using a void pointer in C++?

I want to pass a 2D array of characters to another function using a parameter of type "void*" and then have that function have access to the elements inside that array.
This code spits out a "Segmentation Fault:11" at the point where voidPointer tries to std::cout elements inside array2.
#include <iostream>
void voidPointer(void* userdata) {
char** array2 = static_cast<char**>(userdata);
for (int i=0; i<3; ++i) {
for (int j=0; j<3; ++j) {
std::cout << array2[i][j] << ' ';
}
std::cout << std::endl;
}
return;
}
int main() {
char array[3][3];
for (int i=0; i<3; ++i) {
for (int j=0; j<3; ++j) {
array[i][j] = 'a';
}
}
voidPointer(array);
return 0;
}
I've tried lots of different things and can't figure this out at all. I was able to get the above code to work when it's dealing with a 1D array. For example, this code
#include <iostream>
void voidPointer(void* userdata) {
char* array2 = static_cast<char*>(userdata);
for (int i=0; i<3; ++i) {
std::cout << array2[i] << ' ';
}
std::cout << std::endl;
return;
}
int main() {
char array[3];
for (int i=0; i<3; ++i) {
array[i] = 'a';
}
voidPointer(array);
return 0;
}
works as expected with the output "a a a".
Backstory: I'm working on my first project in which I'm trying to use a Mouse Callback function that accepts a parameter in the form "void* userdata". I am attempting to pass a 2D character array to this Callback function so I can then pass it on to other functions that will require access to the elements inside this array. I don't really know if this is good coding practice or not so feel free to let me know some alternatives.
To anyone that responds, thank you!
Firstly, I'll explain why your second example succeeds but your first example fails. Then I'll suggest some options for consideration to make your code work.
In short - your first example has undefined behaviour because the notional equivalence of pointers and arrays only works in one dimension.
The second example relies on the facts that;
The name of a one-dimensional array can be implicitly converted to a pointer to that array's first element. So, in main() of your second example, voidPointer(array) is equivalent to voidPointer(&array[0]). &array[0] has type char *.
A pointer can survive a round trip via a void * conversion - where "round trip" means retrieving the pointer of the original type. i.e. a char * can be converted to a void * AND that void * can be converted back to a char *. So the explicit conversion char* array2 = static_cast<char*>(userdata) done in voidPointer() successfully retrieves the pointer - so array2 in voidPointer() is equal to &array[0] passed by main();
Since the pointer passed by main() is the address of the first element of the array passed, voidPointer() can safely treat that pointer AS IF it is an array (as long as code doesn't try to access elements out of range of the original array).
The logic above is only applicable for pointers and one-dimensional arrays, so breaks down in the first example;
The name of a one-dimensional array can be implicitly converted to a pointer to that array's first element. So, in main() of your second example, voidPointer(array) is equivalent to voidPointer(&array[0]). However, the difference is that - the expression &array[0] has type char (*)[3] (a pointer to an array of three char) and that is NOT equivalent to a char **.
in voidPointer() your code converts the received pointer to a char ** via char** array2 = static_cast<char**>(userdata). This means that the pointer array2 has a different type that the pointer (&array[0]) passed by main();
Since array2 has a different type than the pointer passed by main() the code in voidPointer() which dereferences array2 (treats it as if it is an array of arrays) has undefined behaviour.
Generally speaking, there are two ways you can make the code work. The first is to do the right type of conversion.
void voidPointer(void* userdata)
{
char (*array2)[3] = static_cast<(char (*)[3]>(userdata);
// rest of your function can be used as is
}
As in your code, the array dimensions (which are both 3 in your example) must be known and fixed at compile time. There is no way that userPointer() can obtain any array dimensions from userdata, because a void * does not carry any of that sort of information from the caller.
A second option is to wrap the array in a data structure, for example
#include <iostream>
struct Carrier {char data[3][3];};
void voidPointer(void* userdata)
{
Carrier *package2 = static_cast<Carrier *>(userdata);
for (int i=0; i<3; ++i)
{
for (int j=0; j<3; ++j)
{
std::cout << package2->data[i][j] << ' ';
}
std::cout << std::endl;
}
}
int main()
{
Carrier package;
for (int i=0; i<3; ++i)
{
for (int j=0; j<3; ++j)
{
package.data[i][j] = 'a';
}
}
voidPointer(&package);
return 0;
}
This works because a Carrier * can survive a round trip via a void pointer (i.e. the value of package2 in voidPointer() has the the same type AND the same value as &package in main()) .
A second option is to use the std::array class. Although this is syntactically different, it is actually a modified version of the first option (since std::array is technically a templated data structure that contains an array of fixed dimension).
#include <iostream>
#include <array>
void voidPointer(void* userdata)
{
std::array<std::array<char, 3>, 3> *package2 = static_cast<std::array<std::array<char, 3>, 3> *>(userdata);
for (int i=0; i<3; ++i)
{
for (int j=0; j<3; ++j)
{
std::cout << (*package2)[i][j] << ' ';
}
std::cout << std::endl;
}
}
int main()
{
std::array<std::array<char, 3>, 3> package;
for (int i=0; i<3; ++i)
{
for (int j=0; j<3; ++j)
{
package[i][j] = 'a';
}
}
voidPointer(&package);
return 0;
}
Since your examples both had array dimensions fixed at compile time (3 in each dimension), my examples do the same. I'll leave extending the above to have dimensions fixed at run time (e.g. as user inputs) as a learning example.
It looks like the question is how to make this scenario work instead of why the attempt failed. For those interested in why the attempt failed, see casting void** to 2D array of int.
Note: It would be better to avoid using void*, but sometimes one has to interface with someone else's C-style API where void* is the traditional way to pass data to a callback.
There is a reasonably common trick for simulating a multi-dimensional array with a one-dimensional array. Using the trick reduces your scenario to the case that works. The trick involves how you access the elements. Instead of declaring char array[DIM1][DIM2] and accessing elements via array[i][j], declare the array to be char array[DIM1 * DIM2] and access elements via array[i*DIM2 + j].
However, remembering this formula is intellectual overhead, consuming brainpower that would be better used elsewhere. Not to mention that I get the dimensions reversed half the time. You could relieve the coder of this overhead by wrapping this array in a class, and hiding the formula in a method for accessing elements. This might look like the following.
class Array2D {
static constexpr unsigned DIM1 = 3;
static constexpr unsigned DIM2 = 3;
char data[DIM1 * DIM2];
public:
char& at(unsigned i, unsigned j) { return data[i*DIM2 + j]; }
// And perhaps other methods
};
You could then create an object of this class, then pass the address of that object to your C-style mouse handler. I.e. if your variable is Array2D array then call voidPointer(&array). This version can be adapted to the situation where the dimensions are not known at compile time.
Then again, if you are going to create a class anyway, why not try to preserve the syntax you are used to (using operator[] twice)? This does assume that the dimensions are compile-time constants.
class Array2D {
static constexpr unsigned DIM1 = 3;
static constexpr unsigned DIM2 = 3;
char data [DIM1][DIM2];
public:
auto& operator[] (unsigned i) { return data[i]; }
// And perhaps other methods
};
Of course, this approach locks you into a single size. It would probably be a good idea to make this a template. It would be even better if someone else did all that work for me.
#include <array>
static constexpr unsigned DIM1 = 3;
static constexpr unsigned DIM2 = 3;
using Array2D = std::array< std::array<char,DIM2>, DIM1 >;
// Note the order: ^^^^ ^^^^
Remember: if your variable is Array2D array then call voidPointer(&array).
Why not to use a structure instead of array. You can define everything in a structure, than pass its address to your function.

C++ Passing Static Array and Dynamic Array By Reference

To fully understand how pointers, values, and references work, I am making a basic C++ program that attempts to tamper with some static and dynamic arrays and understand exactly how they should be passed in.
First I generate a static array of 3 elements. I then pass it into a function that modifies all elements. I then pass it into another function with a slightly different signature, but can also alter the array's values.
Next I generate a dynamically sized array, pass it into a function by reference so that all of the values in this dynamically sized array can be altered.
The code is as follows:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
void changeIndexStaticArrayMethod1(int* stat);
void changeIndexStaticArrayMethod2(int (&stat)[3]);
void changeIndexDynamicArrayMethod1(int* dyn, int size);
int main() {
const int MAX = 3;
int arr[MAX] = { 1,2,3 };
changeIndexStaticArrayMethod1(arr);
cout << arr[0] << endl;
cout << arr[1] << endl;
cout << arr[2] << endl;
cout << endl;
changeIndexStaticArrayMethod2(arr);
cout << arr[0] << endl;
cout << arr[1] << endl;
cout << arr[2] << endl;
int SIZE;
cout << "Please choose a size for the array" << endl;
cin >> SIZE;
int *ne = new int[SIZE];
//Build array
for (int i = 0; i < SIZE; i++) {
ne[i] = i;
}
changeIndexDynamicArrayMethod1(ne, SIZE);
for (int i = 0; i < SIZE; i++) {
cout << "ne[" << i << "] = " << ne[i] << endl;
}
//To hang program
cin >> SIZE;
delete[] arr;
delete[] ne;
return 0;
}
void changeIndexStaticArrayMethod1(int* stat) {
stat[0] = 10;
stat[1] = 20;
stat[2] = 30;
}
void changeIndexStaticArrayMethod2(int (&stat)[3]) {
stat[0] = 40;
stat[1] = 50;
stat[2] = 60;
}
void changeIndexDynamicArrayMethod1(int* dyn, int size) {
for (int i = 0; i < size; i++) {
dyn[i] = i * 10;
}
}
All of the above code works how I want it to, I just have a few questions as to why (some of the methods of passing arrays by reference I have found on other SO questions).
In the changeIndexStaticArrayMethod1() and changeIndexDynamicArrayMethod1() functions, why are we able to use the dereference * operator for our array as reference? My knee jerk reaction is seeing that as practically passing the array in by values since it is the dereference operator. I know that with arrays, it is much different than using variables, but also, why will the following not work for single int variables:
void changeStaticNumber(int* num){
num = 100;
}
Obviously the above will work if we use &num and not int* num, and obviously I don't fully understand the relationship between pointers and arrays, but I cannot figure out why when we pass an array by reference, int* staticArray is ok.
Any explanation for these problems I am having would be much appreciated. Thanks.
why are we able to use the dereference * operator for our array as reference?
The * in C means many things. It can mean the unary indirection ("contents of") operator, it can mean the binary multiplication operator and it can mean a pointer declaration. The int* stat is a pointer declaration.
Since you aren't using the * to dereference the contents of the pointer inside that function, I'm not quite sure what you are asking.
When you take the array name of your array in main(), it "decays" into a pointer to the first element. So what those function do, is to take a pointer by value. If you dereference the pointer by typing *stat = something; you access the actual array in main.
Should you do something weird like changing the pointer itself, for example stat++;, then it will not affect the address used in main. You passed the pointer itself by value, so the pointer is a local copy.
My knee jerk reaction is seeing that as practically passing the array in by values since it is the dereference operator.
You can't really pass arrays by value in C or C++, without resorting to dirty tricks (storing them inside structs or classes). For example, had your function been written as void changeIndexStaticArrayMethod1(int stat[3]) it would still give you a pointer to the first element. It will not pass an array by value, as the syntax might trick you into believing.
why will the following not work for single int variables:
void changeStaticNumber(int* num){ num = 100; }
Because num is the pointer itself, not its contents. In order to write code like that, you could pass the variable by reference int& num. Behind the lines this is really the same thing as passing a pointer, just with simplified syntax.
To understand the relation between pointers and arrays better, start by reading this whole chapter: http://c-faq.com/aryptr/index.html (C and C++ are identical when it comes to pointers).
Let me see if I can take a stab at this.
Pointers are simply address holders. Once you do int * ptr = myarray; --- what you are in tern doing is storing the address of the pointer my array into ptr --- array names are actually pointers to the first memory location in the array. You can use pointer arithmetic to get at everything else for example myarray +1 will point you to the next location or myarray[1].
Passing by value is not very useful when you need to modify your array. Passing in by reference is essentially making a pointer to the array and passing that. Since arrays like vectors are contiguous blocks of memory you can index through them rather easily.
As far as your example goes void changeStaticNumber(int* num){ num = 100; } will not work because what you are attempting to do is store 100 into the pointer's address. If you deference num and make it void changeStaticNumber(int* num){ *num = 100; } it will work because you are actually going one step further and accessing the data that num is pointing to. When you use &num it is essentially the same thing - & just gives you the address of something.
For example if you want to point a pointer to an int what you would do is
int num = 5;
int *ptr = &num;
at this point in time ptr has the same address in num. To print out the data in num or that ptr is pointing to you need to dereference or go one step further as I like to tell myself and dereference to so cout << *ptr;
In both changeIndexStaticArrayMethod1 and changeIndexDynamicArrayMethod1 you are not passing an array there is no pass by reference (which only happens if the parameter type is a reference type -- i.e. with &). The parameter has type int * (pointer to int). You are passing a pointer to int by value. There is no "dereference operator" in either function.
ne is already an int *, so passing it is nothing special. arr is an int [3], an array, not a pointer. In C, when an array-of-T is used in a context that expects a pointer-to-T, it is implicitly converted (without you needing to do anything) to a pointer to its first element. So when you do, changeIndexStaticArrayMethod1(arr), the compiler gets a pointer to the first element of arr, and passes that to the function.
The [] operator works on pointers. a[i] is always guaranteed to be the same as *(a + i). Inside both the changeIndexStaticArrayMethod1 and changeIndexDynamicArrayMethod1 functions, [] is used to access subsequent elements using a pointer to the first element.

Arrays as address constants in functions

I'm teaching myself C++ and had some questions about arrays and pointers. My understanding is that arrays are really just pointers, however, arrays are address constants which cannot be changed.
If this is the case, I was wondering why in my function show2() I was able to change the address of the pointer list. Unlike variables, I thought arrays are passed by reference so I was expecting a compiler error when calling function show2() since I incremented the address of list. But the code works just fine. Can someone please explain?
Thank you!
#include<iostream>
#include<iomanip>
using namespace std;
void show1(double *list, int SIZE)
{
for(int i=0; i < SIZE; i++)
{
cout << setw(5) << *(list+i);
}
cout << endl;
return;
}
void show2(double *list, int SIZE)
{
double *ptr = list;
for(int i=0; i < SIZE; i++)
cout << setw(5) << *list++;
cout << endl;
return;
}
int main()
{
double rates[] = {6.5, 7.2, 7.5, 8.3, 8.6,
9.4, 9.6, 9.8, 10.0};
const int SIZE = sizeof(rates) / sizeof(double);
show1(rates, SIZE);
show2(rates, SIZE);
return 0;
}
My understanding is that arrays are really just pointers
Let's get that out of the way. No, arrays are not pointers. Arrays are a series of objects, all of the same type, contiguous in memory.
Arrays can be passed by reference, but that is not what is usually done. What is usually done, which is what you are doing, is passing a pointer to the first element of the array. Arrays can and will "decay" to a pointer to their first element upon demand. And that's what is happening when you pass rates to show1 and show2.
Inside show1 and show2, list starts out as a pointer to rates[0]. You're free to modify this pointer to point at any other double.
If you wanted to pass an array by reference, it would look like this:
void show3(double (&list)[9]) { ... }
Or the more versatile:
template<size_t SIZE>
void show3(double (&list)[SIZE]) { ... }
Note that what you can't do is pass an array by value (unless it is contained within another object). If you write a function which looks like it is taking an array by value, e.g.
void show4(double list[9]) { ... }
It is actually a pointer, and that number 9 is meaningless. Native arrays suck.
First, arrays are converted to a pointer to the first element when passed as the function argument. BTW, arrays are not pointers, as one example, sizeof(rates) in your code isn't the size of a pointer.
Second, arrays are passed by value since you are not using references.
So in the function show2, you are modifying a pointer, which is fine.
Arrays are not pointers. C++ has inherited "Array-Pointer Equivalence" from C which means that a well-known array variable can decay to a pointer, primarily for the purpose of offset math and for avoiding passing arrays by value:
int array[64];
int* a = array; // equivalent to a = &array[0];
Array's aren't pointers. If you use an array variable name in a pointer context, it will "decay" to a pointer - that is, lose the extended attributes available from an array object.
int array[64];
int* a = array;
std::cout << "array size = " << sizeof(array) << "\n";
std::cout << "a size = " << sizeof(a) << "\n";
std::cout << "(int*)(array) size = " << sizeof((int*)array)) << "\n";
"Array size" will be 256 (int is 4 bytes, 64 of them = 256 bytes), "a size" will be 4 or 8 bytes depending on 32/64 bits, and "(int*)(array)" size will be the same size as the pointer.
People often think that arrays are passed by value. This is not true: http://ideone.com/hAeH18
#include <iostream>
void bump(int arr[3]) {
for (size_t i = 0; i < 3; ++i)
arr[i]++;
}
int main() {
int array[] = { 1, 2, 3 };
bump(array);
for (size_t i = 0; i < 3; ++i)
std::cout << array[i] << "\n";
return 0;
}
This outputs "2, 3, 4" not "1, 2, 3".
This occurs because arrays decay to pointers when passed as function arguments. But to support the syntax for receiving arrays as arrays, C has to be able to treat pointers like arrays in some contexts:
void f1(int* a) { a[0]++; }
void f2(int* a) { (*a)++; }
void f3(int a[]) { a[0]++; }
void f4(int a[]) { (*a)++; }
void f5(int a[1]) { a[0]++; }
void f6(int a[1]) { (*a)++; }
All of these functions produce the same code.
In C, this originated from the fact that array information is lost at compile time. So this function:
void f(int array[])
has no way to tell how large the array it is receiving is. They wanted programmers to be conscious of this and be careful about how/if they passed size information - e.g. in the case of char arrays, instead of size, we have the nul terminator byte.
Unfortunately they didn't choose to make it obvious by diasllowing the representation that makes it look like you are receiving an array with size information intact :(

What's the best way to rewrite this generic function I wrote in C++ in C?

//Prints out a given array
template <typename T>
void print(T t)
{
for(int i = 0; i < t.size(); i++)
{
cout << t[i] << " ";
}
cout << endl;
}
I have an idea but it includes passing the size of the array. Is it possible to avoid this?
*Update
Thanks for all of the answers/ideas but this problem is getting way deeper than my snorkeler can handle. I wanted to rewrite my C++ code in C because it was horribly written and slow. I see now that I have an opportunity to make it even worse in C. I'll rewrite it from the ground up in Python(performance be damned). Thanks again
If you don't have ELEMENTS, it's
#define ELEMENTS(a) (sizeof(a)/sizeof(*a))
Then,
#define print_array(a, specifier) print_array_impl(a, specifier, ELEMENTS(a), sizeof(*a))
void print_array_impl(void* a, char* specifier, size_t asize, size_t elsize)
{
for(int i = 0; i < asize; i++)
{
// corrected based on comment -- unfortunately, not as general
if (strcmp(specifier, "%d") == 0)
printf(specifier, ((int*)a)[i]);
// else if ... // check other specifiers
printf(" ");
}
printf("\n");
}
Use like this
print_array(a, "%d") // if a is a int[]
and, a needs to be an array name, not a pointer (or else ELEMENTS won't work)
You cannot know what is the size of an array without passing the size of that array (except operating with sizeof in static arrays). This is because the a pointer to a block of memory will only point to the base of the block of memory, from which you can know where the array/block of memory starts, but as there is no end defined you cannot determine where it will end.
You either need to set your own length per array and preserve it, and use it with the array like as described:
You can make a new type like:
struct _my_array {
typename arr[MAX];
int n;
} my_array;
OR
struct _my_array {
typename *arr;
int n;
} my_array;
In this case you need to allocate the a block of memory dynamically with new or malloc , and when finished free the memory with delete or free (respectively).
Or you can simply pass the array number of elements through the function.
Another way is to use a special terminator value of your array type which if encountered will be determined as the end of the array. In this case you need not preserve the size. For example a string is '\0' terminated, so all the string functions know that when a '\0' character is encounter in the char array it will consider that the string has end.
UPDATE
Because this is a generic function and the array can be of any type, one thing which you can do is like this:
struct _my_generic_arr {
void *arr;
int n;
int type;
} my_generic_arr;
When populating this array you can use any type. To identify which type, pass an identified in the type component. Each unique value will determine which type does the arr pointer actually points to (was actually the intended type to be pointed). The n will define the length. Now, depending on different values of type make a switch - case or an if - else ladder or nest, and process the array as you need.
It is impossible in c to track the size of an array in other block,,
It would be a better option to pass the size of the array along..
The other option would be to declare a global variable that has the size and using that variable inside the function
Eg,,
int size=<some value>
void main()
{
int arr[<same value>];
}
void print(T t)
{
for(int i = 0; i < size; i++)
{
printf("%d ",t[i]) //assuming T as int
}
printf("\n");
}
In C, you would need to pass two additional parameters: the size of the array (as you mentioned), and some way of indicating how to convert t[i] into a string. To convert t[i] to a string, you could create a custom switch statement to decode possible types, pass a pointer to a function that will return the string pointer, or you could pass the printf format specifier (e.g. "%d" for integer).
The problem is larger than you think. If you have an array of size 12, how do you know what data is held in that array? It could be 3 char*'s (on 32 bit system), 3 int32_t's, or even 12 chars. You have no way of knowing how to interpret the data. The best you could do is to implement your own version of a v-table and putting a print or toString function into it.
typedef struct {
void *array;
size_t length;
int element_width;
printer_t to_string;
} container;
printer_t is a type that describes a function pointer that takes an element pointer and returns a string (or prints it, if you don't want to free the string). This is almost never worth doing in C. That doesn't mean it can't be done. I would emphasize, though, that none of this is intended to imply that it should be done.
The function itself would look something like this:
void print(container *thing)
{
size_t offset;
int width;
char *stringified;
width = thing->element_width;
for (offset = 0; offset * width < thing->length; offset += width)
{
stringified = thing->to_string(thing->array + offset);
printf("%s ", stringified);
free(stringified);
}
}
What this does is essentially turn a struct into a faux class with a function pointer for a method. You could be more object-oriented and put the method in the type being printed and make it an array of those instead. Either way, it's not a good idea. C is for writing C. If you try to write in a different language, you'll end up with all sorts of terrible stuff like this.

Having a problem with pass by reference in two dimensional array in c++

I have a variable called names which is a two dimensional array.
I declared it like below so that there will be maximum of 5 names and each name will consist of 256 characters.
int main(){
char names[5][256];
strcpy(names[0],"John");
strcpy(names[1],"Matt");
printf("%d\n",sizeof(names)/256); //this prints out 5 which is correct
passit(names);
}
void passit(char names[][256]){
printf("%d\n",sizeof(names)/256); //this prints out 8 which seems to be a size of pointer
}
How should I change this so that in passit function, number of elements will be printed correctly?
Your code is C-style. If you're really writing C++ then I suggest using std::cout, std::vector and std::string:
void passit(std::vector<std::string> const& names) {
std::cout << names.size();
}
int main() {
std::vector<std::string> names(5);
names[0] = "John";
names[1] = "Matt";
std::cout << names.size();
passit(names);
}
Otherwise, you can perform an intermediate fix to your existing code.
As you've spotted, when you try to pass an array by value it actually decays to a pointer (char(*)[256] in this case) and you lose all information on the size of the first dimension.
Passing the array by reference avoids this, except that you now have to specify the full array type including all array dimensions; template argument deduction then makes this automatic:
template <size_t N>
void passit(char (&names)[N][256]) {
printf("%d\n", N);
}