What is the purpose of using (*ptr)[5] instead of *ptr? [duplicate] - c

This question already has answers here:
Difference between "pointer to int" and "pointer to array of ints"
(8 answers)
Closed 4 years ago.
I read about (*ptr)[5] that it can point to a 5-element integer array. What this means?

It can be used when you want to go through a 2-d or a higher dimensional array.
For example you have this 2-d array:
int a[3][4] = {
1,2,3,4,
5,6,7,8,
9,0,1,6
};
A normal *ptr will go through each of the elements in the array.
If this array's base address is : 1000. Then the next address it will go to on increment would be 1002, 1004, 1006. Taking sizeof(int) => 2.
What (*ptr)[5] would do is to jump to the next 5th element and then point to it.
In the example taken above, if I want to jump on the very starting of each 1-d array in it, I would simply use (*q)[4] and jump to the next 4th element and just not the very next one.
So if you want to display the elements of this array you can do this in two ways:
Using normal *ptr
void display(int *q, int row, int col){
int i, j;
for(i=0; i<row; i++){
for(j=0; j<col; j++){
printf("%d ", *(q + i*col + j));
}
printf("\n");
}
}
Using (*ptr)[4]
void show(int (*q)[4], int r, int col){
int i, j, *p;
for(i=0; i<r; i++){
p = q+i;
for(j=0; j<col; j++){
printf("%d ", *(p+j));
}
printf("\n");
}
}

int (*q)[5] means that q is a pointer to an array of 5 integers. To understand better let us use this pointer to an array of 5 integers.
void main()
{
int a[][5] = {
1,2,3,4,5,
6,7,8,9,10,
11,12,13,14,15
};
int *p;
int (*q)[5];
p = *a;
printf("%d %d\n",p,q);
p++;
q++;
printf("%d %d\n",p,q);
}
Output:
65500 65500
65502 65510
To begin with, both p and q contain the same address 65500. However, on incrementing p it points to an array of 5 integers.Hence on incrementing p it points to the next integer,
whereas q starts pointing to the next 1-D array of 5 integers. Pointer to the array is very useful while passing a 2D array to functions.

Related

How do Array Pointers behave?

I was trying to write the code for storing multiplication table in array.
First I wrote the following code.
#include<stdio.h>
void Multiplication(int arr[][10], int num,int size);
int main(){
int arr[3][10];
Multiplication(&arr[0],2,3);
Multiplication(&arr[1],7,3);
Multiplication(&arr[2],9,3);
for(int i=0;i<3;i++){
printf("\n\nMultiplication Table of %d\n\n",arr[i][0]);
for(int j=0;j<10;j++){
printf("%d * %d = %d\n",arr[i][0],j,arr[i][j]);
}
}
return 0;
}
void Multiplication(int arr[][10], int num, int size){
for(int j=0;j<size;j++){
for(int i=0;i<10;i++){
arr[j][i] = num * (i+1);
}
}
}
When I was checking whether there is any reduntant part, I removed a little bit of pieces.
#include<stdio.h>
void Multiplication(int *arr, int num,int size);
int main(){
int arr[3][10];
Multiplication(arr[0],2,3);
Multiplication(arr[1],7,3);
Multiplication(arr[2],9,3);
for(int i=0;i<3;i++){
printf("\n\nMultiplication Table of %d\n\n",arr[i][0]);
for(int j=0;j<10;j++){
printf("%d * %d = %d\n",arr[i][0],j,arr[i][j]);
}
}
return 0;
}
void Multiplication(int *arr, int num,int size){
for(int i=0;i<10;i++){
arr[i] = num * (i+1);
}
}
Now, I noticed that &arr[0] and arr[0] are behaving same? I wanna know why is it so?
The following is the question asked:
I noticed that &arr[0] and arr[0] are behaving same? I wanna know why is it so?
We have
int arr[3][10];
arr[0] is a int[10], which is to say an array of 10 int values.
But it's being treated as a pointer. When an array is treated as a pointer, it produces a pointer to the first element of the array. So this means arr[0] is automatically converted to a int* pointing to the first element of the first row of arr when necessary.
&arr[0] means &(arr[0]). It produces a int(*)[10] (a pointer to an array of 10 int values) pointing to the first row of arr.
To recap,
arr[0] is a int[10] which degrades to a int*.
It points to the first element of the first row of arr.
&arr[0] is a int(*)[10].
It points to the first row of arr.
So, arr[0] is NOT equivalent to &arr[0], contrary to your assertion.
And this lack of equivalence is why you had to change from &arr[0] when you when you had int arr[][10] (which means int (*arr)[10] a parameter), to arr[10] when you had int *arr as the parameter.
The both programs are incorrect.
You declared a two dimensional array
int arr[3][10];
So expressions like this arr[0], arr[1], arr[2] have the array type int[10]. That is they produce the first "row", the second "row" and the third "row" of the two-dimensional array.
In the first program you are calling the function Multiplication like
Multiplication(&arr[0],2,3);
Multiplication(&arr[1],7,3);
Multiplication(&arr[2],9,3);
and within the function there are two nested loops
void Multiplication(int arr[][10], int num, int size){
for(int j=0;j<size;j++){
for(int i=0;i<10;i++){
arr[j][i] = num * (i+1);
}
}
}
according to the argument specified for the parameter size the function deals with a two dimensional array with three elements (rows) of the array type int[10] using a pointer to the first element of the array. As a result for the argument expressions &arr[1] and &arr[2] there is an access to the memory beyond the original two dimensional array.
You may consider these calls
Multiplication(&arr[0],2,3);
Multiplication(&arr[1],7,3);
Multiplication(&arr[2],9,3);
like
Multiplication( arr, 2, 3 );
Multiplication( arr + 1, 7, 3 );
Multiplication( arr + 2, 9, 3 );
The array designator arr is implicitly converted to a pointer to its first element (row) of the type int ( * )[10].
As you are setting only one "row" within the array then the function can be declared and defined the following way
void Multiplication(int arr[][10], int num ){
for(int j=0;j < 10;j++){
( *arr )[j]= num * (j+1);
}
}
and called like
Multiplication( arr, 2 );
Multiplication( arr + 1, 7 );
Multiplication( arr +2, 9 );
Of you want to set elements of a sub-array then the function can be defined the way it is defined initially but called like
Multiplication( arr, 2, 3 );
Multiplication( arr + 1, 7, 2 );
Multiplication( arr +2, 9, 1 );
In the second program the function is declared like
void Multiplication(int *arr, int num,int size){
for(int i=0;i<10;i++){
arr[i] = num * (i+1);
}
}
and you are calling it like
Multiplication(arr[0],2,3);
Multiplication(arr[1],7,3);
Multiplication(arr[2],9,3);
But within the function the parameter size is not used. There is used the magic number 10. And the passed argument 3 does not make a sense.
You should declare the function like
void Multiplication(int *arr, int num,int size){
for(int i=0;i<size;i++){
arr[i] = num * (i+1);
}
}
and call it like
Multiplication(arr[0],2,10);
Multiplication(arr[1],7,10);
Multiplication(arr[2],9,10);

How to pass a 2 Dimensional array as an argument of function in C?

Code:
#include <stdio.h>
char* input(char* arr,int N, int M){
int i, j;
for(i=0;i<N;i++){
for(j=0;j<M;j++){
scanf("%d",&arr[i][j]);
}
}
return arr;
}
int main() {
int i,N,M;
scanf("%d%d",&N,&M);
char arr[N][M];
arr=input(arr,N,M);
return 0;
}
Explanation:
The above given is a simple program where the user inputs the data into a 2-D array.
Here I have Tried to assign the value to arr pointer(That points to the base address); an address that we get from the input function, of the same array filled with elements now. We have passed the pointer to the array in input function as one argument, and the array dimensions as the other.
Majorly the problem faced here is about pointers and their application into arrays. But I am not able to figure out how I'll make the changes
There are two ways you can pass a 2D array as a function argument.
char *input (char [][m]arr, int n, int m)
You would read/write values the way you are doing in your code. Keep in mind that this is a feature introduced in C99 and won't compile with older compilers.
Another option is to pass it as a pointer:
char *input (char *arr, int n, int m)
Here you would read or write the array like so:
int i, j;
for(i=0; i<N; i++){
for(j=0; j<M; j++){
*(arr + i * n + j) = 'a';
/* OR you can also do this */
arr[i *n + j] = 'a';
}
}
Multidimensional arrays in C are stored in memory row by row. So if you allocated a 3 x 2 array, you would have 3 rows, each having 2 columns. But the memory layout would be:
0, 1 => row1
2, 3 => row2
4, 5 => row3
Here, 0,1,2,3,4,5 are the contiguous indices of the array. In order to access the 2nd column of 3rd row , given a pointer arr to the base address of the array, you would have to find the address of the correct cell in the array.
We know that each row has 2 cells so in order to jump to the 3rd row we need to add the row_id * number_of_cols_per_row to the base pointer. So to get to 3rd row, we need to do arr + 2 * 2. Once we are in the correct row we need to add the column offset of the column we want to access. So here we want to access the second column, so we add 1.
arr + 2 * 2 + 1
But this will be the address of the second column of the third row. In order to write here we need to use the * operator:
*(arr + 2 * 2 + 1) = 'a';
This is exactly what we are doing in the loop.
As an aside, in your code you are calling scanf with %d format specifier, which is for integers. But you are storing the value in a char array. This can be a potential bug, correct thing is to use %c specifier.
You can use a two-dimensional array masterpiece as an argument or a parameter, you can specify the size of all dimensions when defining the parameter group in the called function, or you can omit the size description of the first dimension, such as:
void Func(int array[3][10]);
void Func(int array[][10]);
Here is a complete solution that works:
#include <stdio.h>
void input(int N, int M, char arr[N][M]){
int i, j;
for(i=0; i<N; i++){
for(j=0; j<M; j++){
scanf("%c", &arr[i][j]);
}
}
}
int main() {
int N, M;
scanf("%d %d", &N, &M);
char arr[N][M];
input(N, M, arr);
return 0;
}

Passing three dimensional arrays to a function in C

I use to program with FORTRAN, but I decided to learn C and C++. I started with C language, and the one thing that I never used are pointers, because FORTRAN pass values by reference. I built the sample code below to understand how pointers work with multidimensional arrays:
#include <stdio.h>
#include <stdlib.h>
#define DIM1 3
#define DIM2 2
#define DIM3 4
void display3DArray1(int, int , int n, int (*arr)[][n]);
void display3DArray2(int rows, int cols1, int cols2,int arr[][cols1][cols2]);
int main(void)
{
int matrix3D[DIM1][DIM2][DIM3] = {
{{1, 2, 3, 4}, {5, 6, 7, 8}},
{{9, 10, 11, 12}, {13, 14, 15, 16}},
{{17, 18, 19, 20}, {21, 22, 23, 24}}
};
int (*pmatrix3D)[DIM2][DIM3] = matrix3D;
display3DArray1(DIM1, DIM2, DIM3,pmatrix3D);
display3DArray2(DIM1, DIM2, DIM3,pmatrix3D);
return 0;
}
void display3DArray1(int rows, int cols1, int cols2,int (*arr)[][cols2]) {
printf("\n");
for(int i=0; i<rows; i++) {
for(int j=0; j<cols1; j++) {
for(int k=0; k<cols2; k++) {
printf("*arr : %d adress: %p\n",*(*((*arr+i*cols1))+j*cols2+k),*((*arr+i*cols1))+j*cols2+k);
}
}
}
}
void display3DArray2(int rows, int cols1, int cols2,int arr[][cols1][cols2]) {
printf("\n");
for(int i=0; i<rows; i++) {
for(int j=0; j<cols1; j++) {
for(int k=0; k<cols2; k++) {
printf("*arr : %d adress: %p\n", *(*(*(arr+i)+j) + k), *(*(arr+i)+j) + k) ;
}
}
}
}
The code works, but there is something that I wasn't able to understand. When I try to use the second printf of the second function in the first one I get a compilation error:
"invalid use of array with unspecified bounds" -- under gcc.
Why *(arr + i) doesn't work in the first function?
You can use the following two ways to pass/print the matrix:
void display3DArray1(int rows, int cols1, int cols2, int *A) {
int *a, i, j, k;
printf("\n");
for(i=0; i<rows; i++) {
for(j=0; j<cols1; j++) {
for(k=0; k<cols2; k++) {
a= A+(i*cols1*cols2)+(j*cols2)+k;
printf("%d, %p\n", *a, a);
}
}
}
}
void display3DArray2(int A[DIM1][DIM2][DIM3]) {
int i, j, k;
printf("\n");
for(i=0; i<DIM1; i++) {
for(j=0; j<DIM2; j++) {
for(k=0; k<DIM3; k++) {
printf("%d, %p\n", A[i][j][k], &A[i][j][k]);
}
}
}
}
The first method does not rely on the dimensions of the matrix; the second one does. As a result, the first one needs explicit address calculations (row i, col j, cell k).
Use calls respectively:
display3DArray1(DIM1, DIM2, DIM3, (int *)matrix3D);
display3DArray2(matrix3D);
Note the cast of the matrix to an int pointer.
In your code, you used parameter names to specify the dimensions of the matrix. In my C version, that is not legal; they must be constants.
Just a complement to Paul Ogilvie's answer.
The correct usage of Variable Length Arrays would be:
void display3DArray3(int rows, int cols1, int cols2,int arr[][cols1][cols2]) {
printf("\n");
for(int i=0; i<rows; i++) {
for(int j=0; j<cols1; j++) {
for(int k=0; k<cols2; k++) {
printf("*arr : %d adress: %p\n", arr[i][j][k], &arr[i][j][k]);
}
}
}
}
I was a bit puzzled, to be honest. The core issue is that the declaration of a function parameter like in f(T arr[]) declares an incomplete type whose size is not known (neither at compile time nor at run time). Originally I thought empty square brackets in function parameter declarations simply declare a pointer — notation notwithstanding —, but that is not the case. The parameter still has array type, albeit incomplete.1
When you write
void display3DArray1(int rows, int cols1, int cols2,int (*arr)[][cols2])
you declare a pointer to such an incomplete type of unknown size. This pointer cannot be manipulated in all the usual ways; in particular, adding to it in order to jump to the next element is impossible because we don't know where the current element ends (and hence the next element starts). But you try that in
printf("*arr : %d adress: %p\n", *(*(*(arr+i)+j) + k), *(*(arr+i)+j) + k) ;
with the innermost arr+1. Just dereferencing it works, because the variable holds the address of the first element all right. This is what the print in the first function does:
printf("*arr : %d adress: %p\n",*(*((*arr+i*cols1))+j*cols2+k),*((*arr+i*cols1))+j*cols2+k);
with *arr. The element size of the incomplete array to which arr points is known (these elements are arrays of cols2 ints), so that we can add to *arr, even if we can't add to arr proper.
For completeness: Why can you access arr that way in the second function? Well:
void display3DArray2(int rows, int cols1, int cols2,int arr[][cols1][cols2])
declares arr as an incomplete array type, true; but the size of its elements is well known: Those are cols1 x cols2 int matrices. The declaration just doesn't specify how many are there, but we can surely iterate them if we somehow know when to stop.
1 Of course this array, like any other, "decays" to a pointer in most contexts, so that the missing type information doesn't matter. But it matters if we have pointers to them.
I had trouble finding the correct syntax for dereferencing matrices of rank2 and rank3. The intent is to remove a level of indexing for faster execution. Here's some pseudo code that will get you started. This is more about getting the syntax right (MSVC 2019) than an example of working code.
int recurse(int n, unsigned char rank2[13][4], unsigned char rank3[13][4][13])
{
if (n < 13)
{
unsigned char (*deRefRank1)[4] = &rank2[n]; // deref matrix rank 2 to rank 1
unsigned char(*deRefRank2)[4][13] = &rank3[n]; // deref matrix rank 3 to 2
// insert pre-recurse code here ... use (*deRefRank1)[] and (*deRefRank2)[][]
if (recurse(n + 1, rank2[n], rank3[n])
return -1;
// insert post-recurse code here ...
}
return 0;
}
Your array indexing in the 'print' routines is invalid. The declaration of 'matrix3D' implies that the type of that name is 'pointer to int'. NOTE: Only one level of indirection there. The indexing expressions have a bunch of ''-s in front of terms; in C that means 'the item to the right of the '' is a pointer which must be dereferenced to get to the value'. That means you are in effect treating 'matrix3D' as 'pointer to (pointer to (pointer to int))' which is too many indirections.

Array pointer in C program

Here is a C program in textbook, it asks a 3*5 2D array from users and prints the third line.
I am confused with int* p[5]. Why here needs to have [5], I think just int* p is OK. It can repeatedly add and point to the next memory space in the int array. And can anyone explain how pointer works in this program?
#include <stdio.h>
int main(void){
int a[3][5];
int i,j;
int *p[5];
p = &a[0];
printf("Please input:\n");
for(i = 0; i < 3; i++){
for(j = 0; j<5;j++){
scanf("%d\n",(*(p+i))+j);
}
}
p = &a[2];
printf("the third line is:\n");
for(j = 0; j<5; j++){
printf("%5d", *((*p)+j));
}
printf("\n");
}
int *p[5];
is an array of five pointers to int.
What you want is a pointer to an array of five ints
int (*p)[5];
because &a[0] is the address of the 1st element of a which is an int[5].
The compiler should have clearly issued at least a warning on this, if not an error, which would be expected.
More on this here: C pointer to array/array of pointers disambiguation

Why are 2D array elements not printed using *(a+1)?

I am trying to accept and print 2D array using same integer lets take i and j but I'm not getting expected output. I'm using *(a+i) to print but it seem to print address!
Could some one please explain why it is happening like this ?
#include<stdio.h>
int main()
{
int a[3][4];
int i,j,k,l;
printf("enter element\n");
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
scanf("%d",&a[i][j]);
}
printf("#####################\n");
for(i=0;i<12;i++)
{
printf("%d\n",*(a+i)); // what is *(a+i)? is it a[i]?
} // how will it print all address??
}
Your answer is very simple you do this for arrays (*(arr+n)) arr is an address and n is the no
of element address you search . If you want to search for addresses into a matrix you must first convert matrix address into a array address something like :
*(*mat+n);
And your code will be:
# include<stdio.h>
int main()
{
int a[3][4];
int i,j,k,l;
printf("enter element\n");
for(i=0; i<3; i++)
{
for(j=0; j<4; j++)
scanf("%d",&a[i][j]);
}
printf("#####################\n");
for(i=0; i<8; i++)
{
printf("%d\n",*(*a+i)); // what is *(a+i)? is it a[i]?
}
}
what is *(a+i)? is it a[i]? - ya it is. you can represent a[i] in many forms. those are *(a+i) or *(i+a) or i[a]. All are representing same memory location only.
In your program *(a+i) wont work with in the same function. Try to pass the array to another function and print there that time it will work. Try the following code-
#include<stdio.h>
void print(int *a,int r ,int c)
{
int i ,j;
for(i=0;i<r*c;i++)
printf("%d\n",*(a+i));
}
int main()
{
int a[2][2];
int i,j,k,l;
printf("enter element\n");
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
scanf("%d",&a[i][j]);
}
printf("#####################\n");
print(a,2,2); // calling my function here
}
But don't prefer this type of methods( *(a+i) for printing 2D array) in real time programming!
*(a+i) is definitely a[i].
Many bugs in your code need to fix first.
Your array reading value goes to out of bound. You defined array by int a[1][4] (room for 1*4 = 4 elements ) and you read 3*4=12 elements.
Also a points to entire 2D array and a+1 point to next 2D array. So you need to access by pointing to first element of the array.
So basically valid access is
a[0][1] = *( a[0] + 1 )
And
for(i=0;i<12;i++)
printf("%d\n",*(a[0]+i));
The best way you can do what you are trying to achieve is to take a pointer to the base address of the 2D array, and then traverse the array linearly as you wanted to do.
Also, as already answered by Sathish, *(a+i) = *(i+a) = a[i] = i[a]
Here, in my solution, I have just added a pointer p which points to the base address of a, and because the 2D array is stored linearly in the memory, you can access it by incrementing the pointer p to the next array element.
#include<stdio.h>
int main()
{
int a[3][4];
int i,j,k,li, *p;
printf("enter element\n");
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
scanf("%d",&a[i][j]);
}
printf("#####################\n");
p = &a[0][0];
for(i=0;i<12;i++)
{
printf("%d\n",*(p+i));
}
}

Resources