pointers, array, functions

Pages: 12
Hey guys I'm too messing with pointers, arrays(oneD, multiD) and arrays(oneD, multiD) as parameters and returns of functions.

so far I've collected this info

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

int x = 5, y = 10, z = 15, i = 20, j = 25;

//one dimensional array
int Arr1[x];
//can be pointed to a pointer
int * ptr1 = Arr1;

//two dimensional array
int Arr2[x][y];
//cannot be pointed to any kind of pointer
//same with arrays with dimensions more than one
int Arr21[x][y][z];
int Arr22[x][y][z][i];
int Arr23[x][y][z][i][j];
//none these arrays can be pointed to any type of pointer

//but a pointer to an array
int * Arr3[y];
//can be pointed to a pointer
int * * ptr3 = Arr3;
//way same works for other arrays having dimensions more than two
int * * Arr31[z];
//can be pointed to pointer like
int * * * ptr31 = Arr31;
//and works way same for arrays having more dimensions

//any pointer
int * * * * * * * POINTER;
//can be pointed to a pointer of that same type
int * * * * * * * POINTER2 = POINTER;


//any array
int Arr4[x];
//can never be return type of any function
Arr[] havefun(){}

//BUT any array
int Arr5[x];
//can be parameter to a function
void myfun(Arr[x]){}
//but can't put in function parameter if don't put it's size in []

//same with two dimensional arrays
int Arr6[x][y];
//but you can skip the first size/dimension/depth or whatever we call
//things inside []
void fun2(Arr[][y]){}

//same with three or even more dimensional arrays
int Arr7[x][y][z];
void fun3(Arr[][y][z]){}

//functions can return any kind of pointer
int * fun4(){}
int * * fun5(){}
int * * * fun6(){}
//and more...

//functions can take any pointer as parameter
void fun7(int * ptr){}
void fun8(int * * ptr){}
void fun9(int * * * ptr){}
//and more...


please help me correct mistakes if any
also other related cases which I'm missing
as I said I wanna mess with pointers, arrays and functions
make me dive as deep as I can PLEASE!!!

Also if there is any general rule(s) for these operations please help me find

Please don't point to tutorials which contain thing which I already have covered in this text
closed account (jvqpDjzh)
line 19:
//but a pointer to an array
int * Arr3[y];
//Array of integer pointers

int Arr23[x][y][z][i][j];

In my opinion, you're complicating your life a bit. Why do you need a multidimensional array like this?

line 21:
int * * ptr3 = Arr3
Here you are declaring a pointer to pointers, which means a pointer that contains pointers, which point to integers

line 31:
int * * * * * * * POINTER2 = POINTER;
Can you explain me what the heck is this?
Last edited on
Before I start this... let me say that multidimensional arrays are code poison. I avoid using them except for rare cases where I need lookup tables... and in those cases I am not passing the arrays between functions.

99.9% of the time, you are better off with a more organized data container, like a custom class/struct or a vector.


That said...
Any type can be pointed to. Arrays are a type.


It's usually easier to visualize with a typedef:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef int int4[4];  // typedef for an array

int4 foo;  // with our typedef, this is the same as 'int foo[4];'

int4* ptr = &foo;  // a pointer to the array
int* ptre = foo;  // a pointer to the first element in the array
    // ie:  this is a shortcut for: 'ptre = &foo[0];'


/////////////////////////////
// of course... the same can be done without the typedef... but then the syntax gets ugly:
int foo[4];

int (*ptr)[4] = &foo;
int* ptre = foo;


With that in mind... multidimentional arrays are just arrays of arrays:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int4 md[3];  // same as: int md[3][4];
  // the [4] array is the "inner" array (there are 3 of these arrays)
  // the [3] array is the "outer" array (there is only 1 of this array)

int4* p = md;  // points to the first inner array.
  // same as: p = &md[0];

int* pe = &md[0][0]; // points to the first int in the first inner array
  // same as: pe = md[0];


int4 (*po)[3] = &md;  // points to the outer array

///////////////////////////////////////////////////////////
//  same code without the typedef:
int md[3][4];

int (*p)[4] = md;  // points to first inner array
int* pe = &md[0][0]; // points to first int in first inner array
int (*po)[3][4] = &md; // points to outer array 


Passing to/from functions works the same with arrays as it does with every other type... with 1 exception: you cannot pass by value. This means you cannot create a "copy" of the array that is passed to the function. Therefore, arrays are usually passed by passing a pointer to the first element:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void func(int* ptr);  // takes a pointer to an int

int foo[4];
func( &foo[0] ); // give a pointer to the first int in our array
func( foo );  // shorter way to do the same thing.

///////////////////////

void func(int4 *ptr); // take a pointer to an int[4] array
// or... without the int4 typedef:
void func(int (*ptr)[4]);

int foo[4];
func( &foo );  // give a pointer to our array

int md[3][4];
func( md ); // give a pointer to the first inner array
func( &md[0] ); // same thing 
Last edited on
int * Arr3[y];
//this could be used as a two dimensional array being manipulated by a pointer

int Arr23[x][y][z][i][j];
//I know this type of crap is not used normally but this was just for the sake of
//mentioning a possible case

int ** ptr3 = Arr3;
//in this case I wanted to mention that " A pointer to an array could be pointed
//to a pointer to a pointer of same type "

int * * * * * * * POINTER2 = POINTER;
//lolx actually just wanted to mention that any level(up to max allowed by
//architecture or maybe C++) pointer can be declared and can be assigned to a
//pointer of that same type
closed account (jvqpDjzh)
An array is actually a pointer to the first element of the same array, so basically you can sometimes interchange the notation of an array with a pointer, see this example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//passing the array to a function using the array notation
//Note that I pass also the size of the array 
//to have the possibility to iterate through all elements 
//and not to go out of the bounds

void increase(int a[], int size)
{
	for(int i=0; i<size; i++) a[i]++;	
}

//passing the array from main through a pointer notation
void show(int* p, int size)
{
	for(int i=0; i<size; i++) std::cout << a[i]<<'\n';	
}

int main(int argc, char** argv) 
{
	int a[5] = {1, 2, 3, 4, 5};
	increase(a, 5);
	show(a, 5);
	
	return 0;
}

Last edited on
I'm not much sure about my this discovery:

//two dimensional array
int Arr2[x][y];
//cannot be pointed to any kind of pointer
//same with arrays with dimensions more than one
int Arr21[x][y][z];
int Arr22[x][y][z][i];
int Arr23[x][y][z][i][j];
//none these arrays can be pointed to any type of pointer


can anybody please confirm this as right, wrong or partially wrong
I had a long post typed up, but then Disch stole my thunder. :P

But anyways:
danicpp wrote:
1
2
 int * Arr3[y];
//this could be used as a two dimensional array being manipulated by a pointer 
This is just a 1-dimensional array of pointers.
I suppose these pointers *could* point to other arrays, but....

zwilu wrote:
An array is actually a pointer to the first element of the same array
Kind of. Arrays can certainly decay into pointers, but they're not actually pointers.
(And they behave differently from pointers in certain cases)

danicpp wrote:
1
2
3
4
5
6
7
8
//two dimensional array
int Arr2[x][y];
//cannot be pointed to any kind of pointer
//same with arrays with dimensions more than one
int Arr21[x][y][z];
int Arr22[x][y][z][i];
int Arr23[x][y][z][i][j];
//none these arrays can be pointed to any type of pointer 
Actually, you can do this:
1
2
3
int (*ptrToArr2)[x][y] = &Arr2;
int (*ptrToArr21)[x][y][z] = &Arr21;
// etc. 
zwilu there is an error in your code I guess

void show(int* p, int size)
{
for(int i=0; i<size; i++) std::cout << a[i]<<'\n';
}

I guess you can't do it a[i] way you will have to use * (p + i) way.
I tested you code and it did give error saying "24 D:\Devcpp Programming\temp\temp.cpp `a' undeclared (first use this function) "
closed account (jvqpDjzh)
zwilu there is an error in your code I guess
guess you can't do it a[i] way you will have to use * (p + i) way.
I tested you code and it did give error saying "24 D:\Devcpp Programming\temp\temp.cpp `a' undeclared (first use this function) "

No dude, it's a typo: I've just forgotten to change a for p:

1
2
3
4
void show(int* p, int size)
{
      for(int i=0; i<size; i++) std::cout << p[i]<<'\n';
}


EDIT: you can also use this notation: * (p + i)
Last edited on
long double main

 
int * Arr3[y];


yes I didn't mean this to be two dimensional array but I meant it could mimic a two dimensional array and I hope we can manipulate it using * ( * (ptr +i) + j ) way,
well actually i did check it right now but I didn't knew the first depth of array and put an arbitrary one then you know what happened, code compiled successfully but when I executed it, it just gave a system error, I guess cause I put arbitrary integer in first depth which could've been anywhere on RAM and I guess it tried to go outside my programs allocation and windows stopped it's execution for safety reason

yes you're right long double my code is faulty not at compile time but at execution time

(And they behave differently from pointers in certain cases)

I was suspecting this same thing for a few days as in a few places I just could not replace pointer with array


int (*ptrToArr2)[x][y] = &Arr2;
int (*ptrToArr21)[x][y][z] = &Arr21;
// etc.

well this way I didn't know "long double main" thanks for adding to my knowledge, well I still wonder how this parenthesis method(*ptr) works, this is first time I'm watching this

well again right now I used this method and this is just AMAZING
Disch

1
2
int (*ptr)[4] = &foo;
in* ptre = foo;


wasn't this supposed to be int* ptre = foo;
also I hope both these lines do same thing for ptr and ptre.
also could we do
int (*ptr)[4] = foo instead of &foo???

also thanks for teaching me this typedef, I hope this is used to append a datatype without having to type it each time if same is needed right???

I'm reading through your post but it's kind of little complex but I will report you till tomorrow after reading it completely
zwilu are x[i] and * ( x + i ) same???
and are they always same??? or just in some specific cases?
wasn't this supposed to be int* ptre = foo;


Yes. Sorry. Typo. I've corrected that in my post. Thanks.


int (*ptr)[4] = foo instead of &foo???


No.

They are mismatching types.

The key is to remember what type each variable is. For example, here we have 4 types:

1
2
3
4
int ar[4];      // type = int4
int (*ptar)[4]; // type = int4*  (a pointer to an int4)
int var;        // type = int
int* ptvar;     // type = int* (a pointer to an int) 


Throw a & before those variables and you get a pointer to whatever type it was:
1
2
3
4
&ar;    // ar was an int4, so &ar is an int4*
&ptar;  // was int4*, now is int4**
&var;   // was int,   now is int*
&ptvar; // was int*,  now is int** 


You can only assign like types. Back to the original example with foo and ptr:
1
2
int foo[4];
int (*ptr)[4] = &foo;


foo is int4
ptr is int4*

Those are 2 different types: one is an array, the other is a pointer to an array. Therefore you cannot assign them.

However.. ptr = &foo works because:
&foo is int4*
ptr is int4*

They're the same type... so they can be assigned.



The only oddity here is that there is an implicit cast that happens when you take an array name without brackets. This is what is confusing for newbies:

1
2
int array[4];
int* ptr = array; // strangely legal... but why? 


This is strange because:
array is int4
ptr is int*

They are different types. So why can you assign them? Why is this legal?

The weirdness here is that if you have an array name (in this case, 'array') and you do not give it braces, it is implicitly cast to a pointer to the first element in the array.

IE:
1
2
3
4
5
6
7
8
9
10
int array[4];  // int4
int* ptr;      // int*

array[0];      // int
&array[0];     // int*
ptr = &array[0]; // both are int*, so assignment is OK

ptr = array; // int* = int4 -- mismatching types... but the compiler will automatically
  // cast 'array' to be '&array[0]'
  // so you get a pointer to the first element.  So this assignment is OK after all. 
Last edited on
closed account (jvqpDjzh)
zwilu are x[i] and * ( x + i ) same???
and are they always same??? or just in some specific cases?

I don't see a situation where you cannot use one rather than the other notation. Usually indexing is used with arrays (it's easier), but I usually use indexing [] with pointers with no problems.

EDIT:I have found this program somewhere on my pc:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
	int b[]={1,2,3,4};
	int* bPtr = b;//&b[0];
	
	cout<<"Array b printed with:\n\n";
	
	cout<<"Array subscript notation:\n";//indexing of the array
	for (int i=0; i<4; i++)
		cout<<"b["<<i+1<<"] = "<<b[i]<<endl;
	
	cout<<endl;
	
	cout<<"Pointer/offset notation, where the pointer is the array name:\n";
	for (int offset=0; offset<4; offset++)
		cout<<"*(b + "<<offset+1<<") = "<<*(b + offset)<<endl;
		
	cout<<endl;		
	
	cout<<"Pointer subscript notation:\n";//indexing of the pointer
	for (int i=0; i<4; i++)
		cout<<"bPtr["<<i+1<<"] = "<<bPtr[i]<<endl;
		
	cout<<endl;
			
	cout<<"Pointer/offset notation:\n";
	for (int offset=0; offset<4; offset++)
		cout<<"*(bPtr + "<<offset+1<<") = "<<*(bPtr + offset)<<endl;
Last edited on
*(bPtr + offset) can replace b[i] but only when
1. it is a matter of array not a single variable
2. bptr had been assigned the address of b[]

correct??? or something else needs to be added/edited.
b[i] and *(b+i) are both interchangeable when:

1) 'b' is an array name
or
2) 'b' is a non-void pointer.


They are not interchangeable for complex types like vector, which overloads the [] operator, but not the + operator.


In general, b[i] is the preferred form because it's the easiest to type, easiest to read, least confusing, most intuitive, and works with complex types.
well

 
int myarray[5];


myarray is same as &myarray[0] seems to be trivial concept but often we miss this and many confusions seem to be redirecting back to this concept, at-least in my case, and a few others I guess.

Whatever but, Thanks guys thankyou all for all the good help you guys made me. Thanks zwilu, Disch and "long double main".
Last edited on
lolx and thanks Disch for adding that function can have duplicate names when their parameters or return type is/are different.

well from all the knowledge I collected I assumed this to be correct

int arr[5][10][20];
int * ptr = (*(*(arr)));

I compiled and yes is correct lolx.

b[i] and *(b+i) are both interchangeable when:

1) 'b' is an array name
or
2) 'b' is a non-void pointer.



from this I conclude that a pointer when declared is a NULL pointer and we cannot start using it unless we put a value in it right???

one more thing I tried to compile
* ptr;
but received an error means we cannot declare a void pointer, isn't it?
Last edited on
from this I conclude that a pointer when declared is a NULL pointer and we cannot start using it unless we put a value in it right???

No, a pointer is not a NULL pointer unless you assign it the value NULL, 0 or nullptr. Yes, you cannot dereference it until you put a valid value in it.


* ptr;
but received an error means we cannot declare a void pointer, isn't it?

A "void pointer" is a pointer to type void: void* ptr;
Pages: 12