[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 305
  • Last Modified:

Quick C++ question on pointers to arrays

I'm trying to get a point to an array, so that I can use it the same way I'l use the original array, Something like:

  void Find( char szAge[20][3]  )
  {
      char *p_szAge[20][3];

      *p_szAge = &szAgeGroup;

      p_szAge[3][1] = '\0'; / / want a pointer to the array act the same way as the original array.

The above gets an error on the line setting the pointer. Is this possible? If so, how do you do it?
0
DickStone
Asked:
DickStone
  • 7
  • 7
  • 4
  • +4
1 Solution
 
jkrCommented:
>>want a pointer to the array act the same way as the original array.

You are passing it by value anyway, so you can just use it that very way:

 void Find( char szAge[20][3]  )
  {
      szAge[3][1] = '\0'; // same variable, just use the one that is passed in

    // ...

Open in new window

0
 
Kent OlsenData Warehouse Architect / DBACommented:
Hi Dick,


      char (*p_szAge)[20][3];


Just change that 1 line.  That should do the trick.

Good Luck,
Kent
0
 
DickStoneAuthor Commented:
jb's comment doesn't really help. I want both arrays to be usable (I'm actually creating a permanent pointer to the original array to be used later).

I tried Kent's. I now get two errors on the = lines:
c:\wfree\winfree.cpp(282): error C2440: '=' : cannot convert from 'char *[][3]' to 'char [20][3]'
1>          There are no conversions to array types, although there are conversions to references or pointers to arrays
1>c:\wfree\winfree.cpp(283): error C2440: '=' : cannot convert from 'char' to 'char [3]'
1>          There are no conversions to array types, although there are conversions to references or pointers to arrays
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Jens FiedererCommented:
Arrays are passed as references anyway.

When you pass an array, you don't generate a copy....if you want TWO copies of an array you have to actually create the second array and fill it in.
0
 
phoffricCommented:
Did you want two arrays initially the same, but when you change one, you are not changing the other? If so, how about trying this:
struct arrayContainer
{
    char szAge[20][3];
};
The assignment and copy operators are defined on this struct and should copy the array when you pass in the struct to a function.
0
 
sarabandeCommented:
in c and c++ arrays are not passed by value to a function. instead an array turns to a pointer to array in the function:

// a2 is an array
char a2[20][3] = { '\0' };  
size_t sza2 = sizeof(a2);  // size is 60

size_t nitems = sizeof(a2)/sizeof(a2[0]);  // 20 items

// a2 is a pointer to array of char[3] arrays
void f(char a2[20][3])
{
       size_t sza2 = sizeof(a2); // size is pointer size (4 or 8)
       // error!!!
       size_t nitems = sizeof(a2)/sizeof(a2[0]);  // 4 / 3 == 2 ????

Open in new window

     

you see, as the a2 has turned to pointer the size of the array is no longer available. the inner dimension of 20 given as information to the compiler has no effect for function f. you may  also omit it with the same result:

// a2 is a pointer to array of char[3] arrays
// the 1st dimension cannot be deduced in f.
void f(char a2[][3], int nitems)
{
      for (int n = 0; n < nitems; ++n)
      ....

Open in new window

you need to pass the number of elements as a 2nd argument.


p_szAge[3][1] = '\0'; / / want a pointer to the array act the same way as the original array.
because the array has turned to pointer in the function, the argument already "IS" the pointer you want. see jkr's comment and sample.

if you want to define a pointer variable which also points to the 2d -array, you would do:

char a2[20][3];
typedef char C3[3];
C3 * pa2 = a2; 

f(pa2);  // equivalent to f(a2);

Open in new window


note, you don't have any char* pointer so far. but you could point with a char * to any C3 element:

char a2[20][3] = { '\0' };
char * p = &a2[10];  

Open in new window


you see arrays and pointers in c and c++ are difficult. you may consider using a struct like phoffric showed or - better - use a container like std::vector for definining 2d arrays:

void f(std::vector<std::vector<char> > A2)
{
     size_t nitems = A2.size();       // number of rows
     size_t nitemlen = A2[0].size();  // number of columns (assumed: all columns have same size)
}

// define 2d-array [20][3] and initialize with binary zeroes 
std::vector<std::vector<char> > A2(20, std::vector<char>(3, '\0')); 
A2[10][2] = '1';

// now pass the array by value as a copy
f(A2);
....

Open in new window

     
the above definitions may look weird but unlike to c arrays the c++ containers safely can be passed by value, by pointer or by reference without type change.

Sara
0
 
DickStoneAuthor Commented:
The final solution, which seems to work, is from sarabande:

  void Find( char szAge[20][3]  )
  {
      typedef char C3[3];
      C3 *p_szAge;
      p_szAge = szAgeGroup;

      p_szAge[3][1] = '\0'; / / want a pointer to the array act the same way as the original array.

Note that it's not necessary to know the length, as that will be built into the contents of the array. Also copying doesn't help -- as I'm trying to get a permanent pointer to an array, so that I can use it later (p_szAge will be external).

I'm going to see if I can increase the point value, since this turned out to be a lot harder than I thought. I thought I was just getting my '*' and '&' wrong.
0
 
DickStoneAuthor Commented:
The final solution, which seems to work, is from sarabande:

  void Find( char szAge[20][3]  )
  {
      typedef char C3[3];
      C3 *p_szAge;
      p_szAge = szAgeGroup;

      p_szAge[3][1] = '\0'; / / want a pointer to the array act the same way as the original array.

Note that it's not necessary to know the length, as that will be built into the contents of the array. Also copying doesn't help -- as I'm trying to get a permanent pointer to an array, so that I can use it later (p_szAge will be external).

I'm going to see if I can increase the point value, since this turned out to be a lot harder than I thought. I thought I was just getting my '*' and '&' wrong.
0
 
trinitrotolueneCommented:
All you need to do is

p_szAge = &szAgeGroup;

and then index into the array as

p_szAge[x][y];

Possibly the other experts mentioned this. Haven't read their solutions
0
 
DickStoneAuthor Commented:
phoffric,

Unfortunately, that's what started this whole this.

p_szAge = &szAgeGroup; results in:

1>  Winfree.cpp
1>c:\wfree\winfree.cpp(294): error C2440: '=' : cannot convert from 'char *[][3]' to 'char *[20][3]'
1>          There are no conversions to array types, although there are conversions to references or pointers to arrays
0
 
phoffricCommented:
>> phoffric,
>> p_szAge = &szAgeGroup; results in:
I never said this.

BTW, in your OP,  you have szAgeGroup, which is not defined anywhere.
0
 
phoffricCommented:
Not knowing what szAgeGroup was put me in a guess state. Since others had answered, I assumed they figured it out. I decided to guess what it was. But my guess must be wrong because the following two solutions from jkr and sara produce the same results.

void Findjkr( char szAge[20][3]  ) 
{ 
   szAge[3][1] = 99; // want a pointer to the array act the same way as the original array.
}

void Findsara( char szAge[20][3]  ) 
{ 
   typedef char C3[3];
   C3 *p_szAge;
   p_szAge = szAge;

   p_szAge[3][1] = 99; // want a pointer to the array act the same way as the original array.
}

int main()
{
   char szAgeGroup[20][3];
   int j,k;
   for(j=0; j<20; ++j)
   {
      for(k=0; k<3; ++k)
      {
         szAgeGroup[j][k] = 10*j + k;
      }
   }
   printf("jkr\n");
   printf("%d\n", szAgeGroup[3][1]);  // 31
   Findjkr(szAgeGroup);
   printf("%d\n\n", szAgeGroup[3][1]);
   szAgeGroup[3][1] = 31; // reset to original value

   printf("sara\n");
   printf("%d\n", szAgeGroup[3][1]);  // 31
   Findsara(szAgeGroup);
   printf("%d\n\n", szAgeGroup[3][1]);
}

Open in new window

And the results are:
jkr
31
99

sara
31
99

Open in new window

0
 
phoffricCommented:
You put down the C++ zone. Do you need a C solution or a C++ solution?
0
 
trinitrotolueneCommented:
DickStone & phoffric

sorry my bad!

I didn't read the question properly and gave a possible solution for a single dimensional array.

Here is a possible solution for the original query. compiled and tested as well.

You need to extend it for your 20x3 dimensions.

void func(char arr[2][2])
{
	char* ptr[2];
	for (int i = 0; i < 2; i++)
	{		
		ptr[i] = arr[i];
	}

	ptr[0][0] = 'c';

}

int main()
{
	
	char arr[2][2] = { { 'b', 'l' }, { 'u', 'e' } };
	func(arr);

	return 0;
}

Open in new window


Note that I'm not copying the array passed and am modifying the original array

Apologies if the query has already been answered but I can never resist fiddling with multi-dimensional arrays using pointers.

That being said DickStone this isn't really a recommended paradigm today. If its C++ you are using you are better off using vectors and if its C there really is no need to favor pointers over the regular array indexing syntax if you aren't familiar with it.
If you are dynamically allocating storage this esoteric syntax can increase the probability of memory leaks and possible access violations especially if you are extending your solution to perhaps 3 or more dimensions.
0
 
trinitrotolueneCommented:
one more option is to use references in C++ rather than use pointers but I guess that's already been mentioned by the experts.
0
 
sarabandeCommented:
the original question was to define a pointer that can be used same way like the original array.

if the array was passed as argument to a function, the argument exactly is such a pointer that behaves like the given array beside that the size information was lost.

but the only way to define such a pointer not using a function argument is to  using a typedef for the char[3] elements, because c and c++ do not allow to define pointers to array variables but only pointers to types.

because of that all the answers which try to prove that array arguments to functions behave like the original array are correct but not a solution to the question asked.

Sara
0
 
phoffricCommented:
@Sara,
It is nice to see such passion in your discussions.
>> the original question was to define a pointer that can be used same way like the original array.
>> because of that all the answers which try to prove that array arguments to functions behave like the original array are correct but not a solution to the question asked.
   Maybe you are right. I just cannot follow all of this. For example, jkr's first post defines a pointer, szAge, as an argument. Sure, it looks like a 2D array, but you, me, jkr, and others know that it is really a pointer. So, it seems to me that if defining a pointer is the requirement, then jkr has certainly done so.

  Now, what concerns me is that the author said that jkr's solution does not work. (I didn't quite understand the reason why it didn't work; but when I compare functionally jkr's solution and your program, I get the same results.) I am not interpreting the question as tightly as you are. I think the author is concerned about functionality rather than technique. There are many ways to skin a cat. Using typedef as you did is one, but contrary to what you said, it is not the only way since typedef is a convenience and never a requirement.

However, it is not for me to decide what the author really wants. I just wanted to point out that both of your posts are functionally identical. Since the author is still active in this thread, I hope he can clarify what exactly is the issue with jkr's post given that the results are identical to yours.

>> but the only way to define such a pointer not using a function argument is to using a typedef for the char[3] elements, because c and c++ do not allow to define pointers to array variables but only pointers to types.
   Not sure if you really meant "only way". Here is your program with the typedef removed:
#include <stdio.h>
void Findjkr( char szAge[20][3]  ) 
{ 
   szAge[5][1] = 99; // want a pointer to the array act the same way as the original array.
}

void Findsara2( char szAge[20][3]  ) 
{ 
   char (*p_szAge)[3]; // pointer to an array of 3 chars
   p_szAge = szAge;

   p_szAge[5][1] = 99; // want a pointer to the array act the same way as the original array.
}

int main()
{
   char szAgeGroup[20][3];
   int j,k;
   for(j=0; j<20; ++j)
   {
      for(k=0; k<3; ++k)
      {
         szAgeGroup[j][k] = 10*j + k;
      }
   }
   printf("jkr\n");
   printf("%d\n", szAgeGroup[5][1]);  // 51
   Findjkr(szAgeGroup);
   printf("%d\n\n", szAgeGroup[5][1]);
   szAgeGroup[5][1] = 51; // reset to original value

   printf("sara2\n");
   printf("%d\n", szAgeGroup[5][1]);  // 51
   Findsara2(szAgeGroup);
   printf("%d\n\n", szAgeGroup[5][1]);
}

Open in new window


The author said "The final solution, which seems to work, is from sarabande". Yet, from my naïve point of view, I don't see how Sara's solution is functionally different from the first post by jkr.
0
 
trinitrotolueneCommented:
completing what I started even though my soln could be interpreted as similar to whats already been mentioned.

Effectively the original array - "arr" can be manipulated using an "array like" syntax via "ptr".
Note that the loop is necessary to ensure that at the end of the loop "ptr" can be viewed as the original array "arr"

void func(char arr[20][3])
{
	char* ptr[20];
	for (int i = 0; i < 20; i++)
	{		
		ptr[i] = arr[i];
	}

	ptr[3][1] = '\0';

}

Open in new window

0
 
DickStoneAuthor Commented:
Just by way of explanation...

I have an array being passed as an argument. I was looking for a way to permanently point to the array with a single external pointer. This would allow other functions to later use the pointer as if it were the original array.

Some solutions, like jkr doesn't accomplish this -- as there is no pointer left for other functions to use.

sarabande solves this by leaving a single pointer to the array, which could be used later.

trinitrotoluene's solution works also, but sets and leaves behind an array of pointers, rather than a single pointer. While working, this is much less space and time efficient than sarabande, so isn't really what I was looking for.
0
 
phoffricCommented:
>> trinitrotoluene's solution works also, but sets and leaves behind an array of pointers, rather than a single pointer.
Ok, you have a point here - you don't want to have an array of pointers.

>> Some solutions, like jkr doesn't accomplish this -- as there is no pointer left for other functions to use.
   Do you mean that you would like to pass a single pointer into other functions? In the first post, jkr defines a single pointer, szAge, which can be passed into other functions. Could you help me understand a little better how that does not work for you?
0
 
DickStoneAuthor Commented:
I probably made a mistake in trying to simplify it.

It's not passed to other functions. It's an external pointer which is later used by other functions. This allows many functions in a very complicated program to extremely efficiently use one of several arrays without knowing which array it is. The efficiency comes from a single assignment in the save, and no loss of efficiency in the use.

The real structure is this (using Sara's method):


static C3 *array_ptr; // this will point to the array
...
char array1[100][3], array2[100][3];,
...
fun1(array1); // causes pointer to point to array1
fun2();
...
fun1(array2);; // causes pointer to point to array2
fun2();
...

void fun1(char array[100][3]) {
  array_ptr = array;    // this saves a pointer to either array1 or array2
}
...

void fun2() {
  CString pick5th =  array_ptr[5] ; // this uses the 5th element of whichever array was pointed to
}
0
 
Kent OlsenData Warehouse Architect / DBACommented:
Hi Dick,

You can pass ANY pointer to a function and have the function declaration dictate how the pointer will be used.

void
F1 (char Array[20][3])
{
}

void
F2 (void *ptr)
{
  char **p;
  p = ptr;
  F1 (p)
}

int
main ()
{
  char MainArray[20][3];

  F1 (MainArray);
  return 0;
}

Open in new window


You may get a pointer conversion warning, but the code should work fine.  And with a bit of tinkering even that pointer conversion warning can be eliminated.

Kent
0
 
phoffricCommented:
Getting rid of warnings is often the hard part. And warnings are usually not allowed in mature projects.
0
 
Kent OlsenData Warehouse Architect / DBACommented:
>> Getting rid of warnings is often the hard part. And warnings are usually not allowed in mature projects.

Agreed.  Just taking another tack.  If called function knows the dimensions of the array, then the pointer is all that's needed.  The pointer can be passed through any number of functions and recast countless times.
0
 
sarabandeCommented:
Not sure if you really meant "only way". Here is your program with the typedef removed:
char (*p_szAge)[3];
nice. i didn't know of this and would have mismatched it with a function pointer (where i also always would use a typedef).

Sara
0
 
DickStoneAuthor Commented:
This turned out to be a much harder question than I expected. Sara got just what I needed.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 7
  • 7
  • 4
  • +4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now