The difference between pointer in 2D and 1D array - c

I practiced today some C code, especially array with return function and pointers.
And I found some code which were really confusing and want to know why it is.
So I have first a function which print all elements out of the array.
void function(int *arr)
{
...
printf("%d, arr[i]);
}
Now in main I have a 2D array and a 1D array.
int array2D[2][2] = {{1,2}, {3,4}};
int array1D[3] = {1,2,3};
function(*array2D); // Why do I need here the derefernce pointer
function(array1D); // why I don't need here the deference pointer
And in another case:
void disp( int *num)
{
printf("%d ", *num);
}
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
for (int i=0; i<10; i++)
{
/* Passing addresses of array elements*/
disp(&arr[i]); // why i need here & and above in the function not
}
}
This is really confusing me right now. Can someone explain me this?

The first line
function(*array2D);
is equivalent to
function(array2D[0]);
So you are passing the first array [1,2]. In C an array decays into a pointer
when it is passed to a function.
However, your function function1 should also get the number of
elements of the array.
void function(int *arr, size_t len)
{
size_t i;
for(i = 0; i < len; ++i)
printf("%d\n", arr[i]);
}
Then you can call it2
int array2D[2][2] = { { 1,2} ,{3,4}};
int array1D[3] = {1,2,3};
function(*array2D, sizeof *array2D / sizeof **array2D);
function(array1D, sizeof array1D / sizeof *array1D);
disp (&arr[i]); // why i need here & and above in the function not
Because arr[i] would give you the value stored at the position i, disp
expects a pointer, so you use the &-operator which returns the address of the
array at the position i, which is also equivalent to arr + i.
1Don't call your functions function. Technically that is valid name, but it
would be better if you give your function more explicit names so that just by
reading the name, you know what the functions does.
2Note that sizeof array / sizeof *array only works with arrays. If you have a
function and you expect an array, you will get only a pointer to the array.
In this case you also would need to pass the length of the array.

We're used to the fact that int mike[10] decays to int *, which points to the first thing in the array. So it seems like int sam[5][10] might also decay to int * pointing to the first element of the array. But int sam[5][10] is not a "two-dimensional array of int" that decays to an int pointer, it's an array of five arrays of ten integers. The first thing in sam is the first of the five arrays, so sam decays to a pointer to an array of ten integers, which type is written int (*)[10], though it rarely is written.
So your array2D decays to a different type than integer pointer, which is why your call function(array2D); creates a type mismatch. But your call function(*array2D); does work because (as noted above) *array2D is the same as array2D[0], which is an array of integers, and does decay to int *.
For your second case, arr is an array, but arr[i] is an int, since it is just one position in the array. The ampersand operator makes a pointer of what it operates, so &arr[i] is a pointer, and the call works.

Related

How to print array of element which is store in pointer to an array and this pointer to an array is store in array of pointer?

Hi How to print array of element which is sotre in pointer to an array and this pointer to an array is store in array of pointer?
/* note- ptoa is pointer to an array
aofp is array of pointer */
#include<stdio.h>
int main() {
int i;
int arr[3] = {1,2,3}; // integer array with 3 integers
int (*ptoa)[3]; // ponter to an array
ptoa = &arr; // here i am storing 3 integer
// to ponter to an array
int *aofp[1]; // this is array of pointer
aofp[1] = ptoa; // here i am sotring pointer to an array
/* here i am trying to print all element of arr[3]
using aofp i.e array of pointer*/
for (i = 0; i < 3; i++)
printf("%d", **aofp[i]); // i know this is invalid
//please help me i want print all
//element of arr i.e 1,2,3 using aofp?
}
The Problem
int *aofp[1]; // this is array of pointer
aofp is a one-element array of pointer to int.
aofp[1]=ptoa; // here i am sotring pointer to an array
Here you are trying to assign a pointer to array of int to aofp. These are not compatible types. Also, element [1] doesn't exist. You have two options here, possibly more:
Option 1
You need to declare aofp with the correct type, and access element [0]:
int (*aofp[1])[3];
aofp[0]=ptoa;
for(i=0;i<3;i++)
printf("%d",(*aofp[0])[i]);
putchar ('\n');
The parenthesis in the declaration of aofp are important, because int *aofp[1][3] would be an array-of-array-of-pointers, rather than an array-of-pointers-to-array. Accessing the values of the array uses the same syntax as the declaration. Retrieve element [0] of the array of pointers, dereference the pointer (*), and retrieve element [i] of the array of ints.
However, all this is unnecessarily convoluted, because a one-element array of pointers is pretty much the same as a single pointer. You might as well declare aofp as a pointer to array of int:
int (*aofp)[3];
And now we see that the type of aofp is exactly the same as that of ptoa. You could just as well skip aofp and print out the array pointed at by ptoa directly:
for (i=0;i<3;i++)
printf("%d",(*ptoa)[i]);
putchar ('\n');
Of course, aofp might be declared to have more than one element at a later time.
Option 2
You need to assign a pointer-to-int to aofp[0]. Since ptoa is a pointer-to-array-of-int, dereferencing it results in a pointer to the first element of the int array. (Actually the result is an expression of type array-of-int, but you can't have array values in C, so it is immediately converted to a pointer-to-int.)
int *aofp[1];
aofp[0] = *ptoa;
for (i=0;i<3;i++)
printf("%d",aofp[0][i]);
putchar ('\n');
And, like the previous example, a single-element array is rather useless. You might as well write:
int *aofp;
aofp = *ptoa;
for (i=0;i<3;i++)
printf("%d",aofp[i]);
putchar ('\n');
Or just print out arr[i] directly.
Final note
You may have noticed that I have added a putchar ('\n') call at the end. The reason for this is that a C program might not produce any visible result unless it ends with a new-line.
Okay, you start off all good, except for the typing mistakes in comments maybe; but then you start doing invalid actions after some point, specifically at the line:
int *aofp[1];
This itself is all good actually. You are properly declaring a variable called aofp here, as an array of pointers to integers with a single element, with this statement. However, with the next line:
aofp[1]=ptoa;
It appears that you did not really want to declare that as an array of pointers to integers with a single element, but rather as an array of pointers to arrays of integers with three elements with a single element. This is because, the latter italicised thing is exactly what ptoa is of.
Another important thing here is that arrays in C are zero-based, which means that if you declare an array with the size denoted within square-brackets during declaration, the elements are indexed from [0] to [size - 1], so you should be making the assignment like:
aofp[0]=ptoa;
But this is only after declaring the aofp properly as I've mentioned.
The following code would be the thoroughly corrected version of your code, without changing the way you're handling the job:
#include<stdio.h>
int main( )
{
int i;
int arr[3] = {1, 2, 3};
int(*ptoa)[3];
ptoa = &arr;
// previously was: int *aofp[1];
int(*aofp[1])[3]; // aofp is declared as an
/* 1 2 3 4 */ // array of 1 (3)
// pointer to (2)
// array of 3 (4)
// integers (1)
// previously was: aofp[1] = ptoa;
aofp[0] = ptoa;
for (i = 0; i<3; i++)
// previously was: printf("%d", **aofp[i]);
printf("%d", (*aofp[0])[i]);
return 0; // should be there in C
}
For a code that compiles without warnings/errors, although it might be violating some rules, the following minimal changes could be done:
At your own risk.
aofp[1]=ptoa; to aofp[0] = (int *) ptoa;
**aofp[i] inside printf to (*((int (*)[3]) aofp[0]))[i]
Should do it, but I wouldn't recommend it.
this is exactly what you want:
int main()
{
int i;
int arr[3]={1,2,3};// integer array with 3 integers
int *ptoa = arr;// ponter to an array
int *aofp[1]; // this is array of pointer
aofp[0]=ptoa; // here i am sotring pointer to an array
for(i=0;i<3;i++)
printf("%d",*aofp[0]+i);
}
Is it this what you want to do (http://coliru.stacked-crooked.com/a/f342849a8018de37)?
/* note- ptoa is pointer to an array
aofp is array of pointer */
#include<stdio.h>
int main()
{
int i;
int arr[3]={1,2,3}; // integer array with 3 integers
int* ptoa = arr; // pointer to an array
int* aofp[3]; // this is array of pointer
aofp[0] = ptoa; // here i am storing pointer to an element of array
aofp[1] = ptoa+1; // here i am storing pointer to an element of array
aofp[2] = ptoa+2; // here i am storing pointer to an element of array
/* here i am trying to print all element of arr[3]
using aofp i.e array of pointer*/
for(i=0;i<3;i++)
printf("%d", *aofp[i]);
}

Passing array as parameter

I want to pass an array as a parameter to another function:
int i;
int main()
{
int a[5] = {1, 2, 3, 4, 5};
printf("Main:\n");
for(i=0; i<sizeof(a)/sizeof(int); i++)
{
printf("%i\n", a[i]);
}
func(a);
return;
}
void func(int a[])
{
printf("Func:\n");
for(i=0; i<sizeof(a)/sizeof(int); i++)
{
printf("%i\n", a[i]);
}
}
The loop in the main function prints all 5 values:
Main:
1
2
3
4
5
But the loop in the function func only prints 2 values:
Func:
1
2
Why this strange behaviour?
I want to pass an array as a parameter to another function:
This is a common pitfall. Arrays do not bring along their length, as they do in other languages. A C "array" is just a bunch of contiguous values, so sizeof will not (necessarily) return the length of the array.
What actually happens is that the function gets passed a pointer to the area of memory where the array is stored (and therefore, to the first element of the array), but no information about that area's size. To "pass an array with size", you must do something to provide the extra information:
explicitly pass also its length as an extra parameter. Safer: you can pass uninitialized arrays.
use a special "terminating" value on the array. More compact: you pass only one parameter, the pointer to the array.
(suggested implicitly by #CisNOTthatGOODbutISOisTHATBAD's comment): pass a pointer to a struct holding a pointer to the memory and a size_t length in elements (or in bytes). This has the advantage of allowing to store yet more metadata about the array.
For arrays of integral type, you could even store the length in the first (zeroth) element of the array. This can sometimes be useful when porting from languages that have 'measured' arrays and indexes starting from 1. In all other cases, go for method #1. Faster, safer, and in my opinion clearer.
Strings are arrays of characters that employ a variation of method #2: they are terminated by a special value (zero).
Using method #1, your function would become:
void func(size_t n, int a[])
{
printf("Func:\n");
for (i=0; i < n; i++)
{
printf("%i\n", a[i]);
}
}
(it is equivalent to void func(size_t n, int *a) ).
Declaring a function with a parameter of array type is equivalent to declaring it with a parameter of pointer type, i.e. your function is equivalent to:
void func(int *a)
As such, the computation of sizeof(a) inside func computes the size of an int *, not the size of the original array (5 * sizeof(int)).
Since the size of an int * on your platform is apparently twice the size of an int, you see two values printed inside the function in contrast to the five printed outside it (where sizeof(a) correctly computes the size of the array).
This is all related to the fact that when you pass an array to a function, what you're actually doing is passing a pointer to its first element.
Note in passing that this is a FAQ of the comp.lang.c newsgroup:
http://c-faq.com/~scs/cgi-bin/faqcat.cgi?sec=aryptr#aryparmsize
I would change the code to this:
int i;
const int N = 5;
int main()
{
int a[N] = {1, 2, 3, 4, 5};
printf("Main:\n");
for(i=0; i<N; i++)
{
printf("%i\n", a[i]);
}
func(a);
return;
}
void func(int a[])
{
printf("Func:\n");
for(i=0; i<N; i++)
{
printf("%i\n", a[i]);
}
}
Parameter N is constant and define size of array.
I think it is better way, then 2 parameters in function.

Pointer of void array

I have an array of void-Pointers and want to access the elements (inititialize them), but it do not work:
void* anyptr = ...; //a pointer to something
void* arr = (void*)malloc(sizeof(void*)*10);
int i=0;
for(i=0; i<10; i++)
*(arr+i) = anyptr; //dont work, (arr+n) = anyptr; doesn´t work too
I guess, the reason why this won´t work is that on the left side is the result of element i. But i don´t have an idea how to do this
There are two ways to initialize arrays in C:
On the stack (which will handle memory for you since it will be cleaned up when your function ends)
In the heap (which will require you to handle allocation and freeing on your own).
If you would like to use the stack, you could initialize your array like this...
#define ARRAY_LENGTH 10
void *ptr;
void *arr[ARRAY_LENGTH];
for (int i = 0; i < ARRAY_LENGTH; i++) {
arr[i] = ptr;
}
You can similarly define your array in the heap as follows...
#define ARRAY_LENGTH 10
void *ptr;
void **arr = malloc(sizeof(void *) * ARRAY_LENGTH);
for (int i = 0; i < ARRAY_LENGTH; i++) {
arr[i] = ptr;
}
free(arr);
It is important to remember that an array (besides arrays assigned in the stack, which have some additional attributes such as length) is essentially just a pointer to the first element, and the operation arr[i] is the same as moving i*sizeof(elem) bytes away from the first element, and accessing the memory there. If you would like to get a pointer to the ith index in the array, then you would use notations such as...
void *indexPtr = arr + i;
or
void *indexPtr = &( arr[i] );
In this fashion, an array of void*'s would be of type void **, since the variable is a pointer to the first member of the array, which is a pointer. This can be a bit confusing, but just always try to keep in mind what type the elements of the array are, and creating a pointer to them. So if the array is of type int, then the array would be of type int or int[], but if you are storing pointers to integers, you would initialize an array of type int * in either of these two forms...
int **arr = malloc(sizeof(int *) * ARRAY_LENGTH);
int *arr[ARRAY_LENGTH];
Also note that you are storing pointers, so if you run the code...
int *arr[4];
for (int i = 0; i < ARRAY_LENGTH; i++) {
arr[i] = &i;
}
Although it may seem to be that the values pointed to in the array would be as follows- [0, 1, 2, 3], but in reality it would be [4, 4, 4, 4], since what you actually have is an array of pointers all pointing to the variable i in your function, so whenever you change that, the values pointed to in the array will all be changed.
I hope this helped
You need to change this line
void* arr = (void*)malloc(sizeof(void*)*10);
to this
void** arr = malloc(sizeof(void*)*10);
You can't dereference a void pointer. That's the whole point of void pointers.
Dereferencing a pointer provides you with access to the item that's found at the address the pointer points to. With a void pointer, however, you don't know how large the target object is (is it a 1B character or a 100B struct?). You have to cast it to a specific pointer type before dereferencing it.
Adding (or subtracting) an integer i to a pointer is then defined as adding i-times sizeof(*pointer) to the pointer's content. (You can only tell sizeof(*pointer) if your pointer has a specific type. Pointer arithmetic with void pointers makes no sense).
As for (arr+n)= anyptr;, arr+n is just an address. It's not a value you can assign something to (not an lvalue).

How to navigate through arrays using pointers?

Why isn't my code working?
#include <stdio.h>
int main()
{
int test[] = { 3, 9, 7 };
printf("%d", find(test, 3));
return 0;
}
int find (int array[], int size)
{
int i, largest, where;
largest = array [0];
for (i=0; i<size; ++i) {
if (array[i]>largest) {
largest = array[i];
where = i;
}
}
return (int) *(&array+sizeof(int)*where);
}
I know I can replace:
return (int) *(&array+sizeof(int)*where);
with:
return array[where];
but that isn't the point of the exercise.
Pointer arithmetic doesn't work the you think it does. You're looking for:
return *(array + where);
array is already a pointer, and pointer arithmetic just "does the right thing" when adding.
You might be confusing yourself because of the int array[] in your function signature - that's just syntatic sugar for int *array. You really have a pointer, not an array.
Since there is some misinformation flying around in other answers, I'm going to write a more complete explanation here. This function signature:
int find(int array[], int size)
really means:
int find(int *array, int size)
The use of the [] is just syntactic sugar, as mentioned above. When you call the function, like:
find(test, 3);
test is decaying automatically into a pointer to its first element. It's identical to if you had called:
find(&test[0], 3);
Now, looking at your return statement, you can see that:
return (int) *(&array+sizeof(int)*where);
Doesn't make sense - first of all &array is the address of parameter - in this case a pointer parameter, but that doesn't really matter. If you add to it and dereference, you're going to return some random data from your stack, not not from the array you want to.
Secondly, the multiplication by sizeof(int) is unnecessary. Pointer arithmetic in C already includes an implicit multiplication by the size of the pointed-to type. What you're really trying to return is:
return array[where];
which is equivalent to:
return *(array + where);
You're greatly overcomplicating this...
return array[where]; // this means, take the base memory location of "array" then
// add in an offset of where and dereference the result
That's exactly the same as:
return *(array + where);
The fact is that in your main function you have an array called test, once you pass this to your find() function the array will decay to a pointer. So if you now know that you have a pointer you should see why you shoud not be grabbing the address like this:
&array
And you don't need to be adding the "sizeof" offset, because that's given by the type of the pointer (int *)
You should do:
return *(array+where);
since where is the offset to the array. You don't need sizeof(int) anymore

Array of pointers to arrays

I am new to C programming and this is my problem:
I want to store the first value of each array in a new array, then the second value of each array in a new array and so on.
I could declare the array of pointers but I don't know how I use it!
Please I need Help.
int main()
{
int t1[4]={0,1,2,3};
int t2[4]={4,5,6,7};
int t3[4]={8,9,10,11};
int t4[4]={12,13,14,15};
int *tab[4]={t1,t2,t3,t4};
int i,j,k,l;
for (i=0; i<4;i++)
{
printf("%d\t", *tab[i]);
}
return 0;
}
When I do this, I store just the first value of each array.
Your terminology is a little bit all over the place. I think the easiest way to answer your question is to go through your code line by line.
int main()
{
int t1[4]={0,1,2,3}; //Declares a 4 integer array "0,1,2,3"
int t2[4]={4,5,6,7}; //Declares a 4 integer array "4,5,6,7"
int t3[4]={8,9,10,11}; //Declares a 4 integer array "8,9,10,11"
int t4[4]={12,13,14,15}; //Declares a 4 integer array "12,13,14,15"
int *tab[4]={t1,t2,t3,t4};//Declares a 4 pointer of integers array "address of the first element of t1, address of the first element of t2, ..."
int i,j,k,l; //Declares 4 integer variables: i,j,k,l
for (i=0; i<4;i++)
{
printf("%d\t", *tab[i]); //print out the integer that is pointed to by the i-th pointer in the tab array (i.e. t1[0], t2[0], t3[0], t4[0])
}
return 0;
}
Everything you are doing seems ok until your loop. You are showing only the first integer of every array because you are not going through them. To iterate over them, your code should look like this:
for (i=0; i<4;i++)
{
for (j=0; j<4; j++)
{
printf("%d\t", *(tab[j] + i));
}
}
The above code uses two loop counters, one (the i) to go through the positions in the array (first value in the array, second value in the array, etc.); the other to go through the different arrays (the j). It does this by retrieving the pointer stored in tab[j] and creating a new pointer that has the right offset to show the value for the ith column. This is called pointer arithmetic (there is additional information about pointer arithmetic here)
Most people find the syntax *(tab[j] + i) to be clunky, but it is more descriptive of what is actually happening. In C, you can rewrite it as tab[j][i], which is much more usual.
You have stored the data as you intended, you just need to access it properly
for (i=0; i<4;i++)
{
for (j = 0; j < 4; j++) {
int* temp = tab[i];
printf("%d\t", temp[j]); // or try the next line...
printf("%d\t", *(temp + j)); // prints same value as above line
printf("%d\t", tab[i][j]; // the same value printed again
}
}
All of the above print the same value, it is just different ways of accessing that value using pointer arithmetic. Each element of tab is a int* the value of each is the address of your other defined int[] arrays at the start
Edit: In response to the comment of Jerome, you can achieve that by declaring 4 arrays
int tab1[4]={*t1,*t2,*t3,*t4};
int tab2[4]={*(t1+1),*(t2+1),*(t3+1),*(t4+1)};
int tab3[4]={*(t1+2),*(t2+2),*(t3+2),*(t4+2)};
int tab4[4]={*(t1+3),*(t2+3),*(t3+3),*(t4+3)};
Now tab1 contains the first elements of each array, tab2 the second elements, and so on.
Then you can use
int *tttt[4]={tab1,tab2,tab3,tab4};
for (i=0; i<4;i++) {
for (j = 0; j < 4; j++) {
printf("%d\t", tttt[i][j]);
}
}
to print what you wanted. If you declared another pointer array like you did at the start
int* tab[4] = {t1,t2,t3,t4};
then essentially in matrix terms, tttt is the transpose of tab
You store everything but you just don't show it. Try
for (i=0; i<4;i++)
{
for (j=0; j<4; j++)
printf("%d\t", *(tab[i]+j));
}
int* (*a[5])[5][5][5] declares an array of 5 pointers to a 3d array of pointers to ints
int* (*(*a[5])[5])[5][5][5] declares an array of 5 pointers to an array of 5 pointers to a 3d array of pointers to ints.
#include <stdio.h>
int main()
{
int t1[4]={0,1,2,3};
int t2[4]={4,5,6,7};
int t3[4]={8,9,10,11};
int t4[4]={12,13,14,15};
int (*tab[4])[4]={&t1,&t2,&t3,&t4};
int i,j,k,l;
for (i=0; i<4;i++)
{
printf("%d\t", (*tab[i])[1]);
}
return 0;
}
There's a difference between t2 and &t2. Though they have the same value their types are different. int [4] vs int (*)[4]. The compiler will throw a warning (clang) or error (gcc).
int a[4] is conceptually at compiler level a pointer to an array of 4 as well as being the array itself (&a == a).
int (*a)[4] is conceptually at compiler level a pointer to a pointer to an array of 4 as well as being a pointer to the array itself (a == *a) because it's pointing to an array type where the above is true.
At runtime, if an int * and int (*a)[4] point to the same address, they are physically identical – it's just an address, the same address. The type only matters in how the compiler interprets and produces arithmetic operations with that address and the assembly it actually outputs based on the type. You can cast the address to any type you want in order to achieve the desired code output to manipulate data at the address it holds. An int a[4] type however is physically the array itself but you use it as if there is a pointer a to it in memory which is given the same address as the array itself. A pointer to int a[4] means 'a pointer to the address range a that is treated by the compiler as an array with int element width, where the compiler treats the start of the array as if it were a pointer to the array', and any operations on that type will be consistent in a derefernce chain i.e. you must at compiler level use (*a)[0] to access the first element if the type is a pointer to an array, but if you cast the same address to int * then you need to use a[0] to access the member.

Resources