I need to get a pointer to a 2D array. The sizes ARE known at compile time if that helps. I need to perform an action a certain array based on the incoming value of a variable.
//Global arrays
// int c[6000][1000];
// int a[6000][1000];
void fun(int x){
//Setup a pointer here
//Possible solution: int (*pointer)[6000][1000];
int **pointer;
if (x == 0){
pointer = c;
}
else{
pointer = a;
}
//Modify pointer here and have changes reflect back to the array it was based off of
pointer[0][17] = 42;
}
I have looked at close to a dozen different stack overflow articles on how to do this but I cannot find a way to just a get a simple pointer to a 2D array.
//Global arrays
int c[6000][1000];
int a[6000][1000];
void fun(int x) {
int (* ptr)[1000];
if (x == 0) {
ptr = c;
} else {
ptr = a;
}
ptr[0][17] = 42;
}
Like this
//Global arrays
int c[6000][1000];
int a[6000][1000];
void fun(int x) {
if (x == 0) {
c[0][17] = 42;
} else {
a[0][17] = 42;
}
}
Accessing a 2D array using Pointers:
2D array is an array of 1D arrays which implies each row of a 2D array is a 1D array. So, think about two of your global arrays,
int c[6000][1000] and int a[6000][1000].
We can say c[0] is the address of row 0 of the first global 2D array. Similarly a[6000] is the address of row 6000 of the second global 2D array.
Now you want to find the c[0][17] and point that using a pointer which is basically, c[0][17] = *(c[0] + 17).
Also you can write for any other array elements, c[0] = *c and in general each element as, c[i][j] = *(c[i] + j) = ((c+i) + j).
So, if c is a 2D array of integer type then we can think that c is a pointer to a pointer to an integer which can be interpreted as int **c. Dereferencing *c gives you the address of row 0 or c[0] which is a pointer to an integer and again dereferencing c[0] gives you the first element of the 2D array, c[0][0] which is an integer.
You can test your code by accessing each element using pointer for a better understanding:
#include<stdio.h>
#include<stdlib.h>
//Global arrays
int c[6000][1000];
int a[6000][1000];
void fun(int x){
//Setup a pointer here
//Possible solution: int (*pointer)[6000][1000];
int (*pointer)[1000];
if (x == 0){
pointer = c;
}
else{
pointer = a;
}
//Modify pointer here and have changes reflect back to the array it was based off of
pointer[0][17] = 42;
}
int main(){
int num;
scanf("%d", &num);
fun(num);
if(num == 0){
printf("When num is %d, c[0][17] = %d\n", num, *(*(c) + 17));
}
else{
printf("When num is %d, a[0][17] = %d\n", num, *(a[0] + 17));
}
return 0;
}
Related
1)
How to access array element with array of pointers?
By pointer to an array we can access like this (∗a)[0]
,(∗a)[22]
,….. like this
right?
but how with array of pointer?
2)
Check these three codes , one of them use array and one of them use array of pointer, and 3rd one using double pointer, but all giving same output. Why??
#include <stdio.h>
int ptr[12];
int main(void) {
if(*(ptr+5)==*(ptr+3)){
printf("Equal");
}
else{
printf("Not Equal");
}
return 0;
}
#include <stdio.h>
int *ptr[12];
int main(void) {
if(*(ptr+5)==*(ptr+3)){
printf("Equal");
}
else{
printf("Not Equal");
}
return 0;
}
#include <stdio.h>
int **ptr[12];
int main(void) {
if(*(ptr+5)==*(ptr+3)){
printf("Equal");
}
else{
printf("Not Equal");
}
return 0;
}
In *(ptr+5):
ptr is the name of an array.
When an array is used in an expression and is not the operand of sizeof or unary & and is not a string literal used to initialize an array, it is converted to a pointer to its first element. So ptr points to element 0 of the array.
ptr+5 adds five, resulting in a pointer to element 5 of the array.
* dereferences the pointer, producing the contents of element 5 of the array.
Since the array is defined outside any function, it is initialized to zero. Therefore element 5 is zero, so *(ptr+5) is zero. Similarly, *(ptr+3) is zero, so comparing them shows they are equal.
The examples with int ptr[12];, int *ptr[12];, and int **ptr[12]; just change the types of the elements in the array. In each case *(ptr+5) and *(ptr+3) refer to elements 5 and 3 of the array. In each case, the values of the elements are zero (null pointers for the pointer types).
If you want to see differences between different elements of the array, then assign different values to the elements of the array.
Just keep incrementing the pointer as you go along reading the array. Analyze the
code below:
#include <stdio.h>
int main(void) {
int *ptr[3];
int a[] = { 0,1,2};
int b[] = { 3,4,5 };
int c[] = { 6,7,8 };
ptr[0] = a;
ptr[1] = b;
ptr[2] = c;
for (int i = 0;i < 3;i++)
printf("%d %d %d\n",*ptr[0]++,*ptr[1]++,*ptr[2]++);
return 0;
}
Answered in comments.
I'm coming from c#, and this is causing me more issues than I would've expected. I've not seen a straight forward solution to this. I'm brand new to C, just playing with it, and all of the various implementation I've tried, from using structs, to passing pointers around isn't getting the job done. (local values aren't changing). Can someone give me a cut and dry example?
Here's a sample of my code
#include <stdio.h>
//alter values based on input
int * doStuff(int a, int b){
int input;
int arr[2]
scanf("%d", &option);
switch(option);
case 1:
arr[0] = a-2;
arr[1] = b;
return arr;
break;
case 2:
arr[0] = a;
arr[1] = b-2;
return arr;
break;
default:
return a, b;
}
main(){
int a = 20;
int b = 20;
int returnedObject[2];
//what i need is like in c# how I can do this
returnedObject = doStuff(a, b);
a = returnedObject[0];
b= returnedObject[1];
}
I need to pass values, alter them, return them, and set the local variables. I'm completely lost with some of the more complex examples. Coming from c# pointers, arrays, how they work is losing me, and it isn't as simple as I had expected.
Functions in C cannot return array types, nor can arrays be the target of an assignment. So code like
int returnedObject[2];
returnedObject = doStuff( a, b );
cannot work. C functions can return pointers to arrays, but I don't think you want to get into that.
C functions cannot return multiple objects, nor is multiple assignment supported.
If your two values are logically attributes of some larger, aggregate type, you can use a struct type to return a single object with multiple attributes, such as
struct result { int x, int y };
struct result doStuff( int a, int b )
{
struct result ret = {a, b}; // initialize struct with inputs
...
case 1:
ret.x = a-2;
break; // y remains unchanged
case 2:
ret.y = b-2;
break; // x remains unchanged
...
return ret;
}
which you would call as
struct result stuff;
stuff = doStuff( a, b );
Alternately, you can pass pointers to your values and update them as necessary:
void doStuff( int *a, int *b )
{
...
case 1:
*a = *a - 2;
break;
case 2:
*b = *b - 2;
break;
}
which you would call as
doStuff( &a, &b );
In this case you don't actually return anything to the caller.
You can pass an array as an argument to the function, like so:
void doStuff( int a, int b, int *result )
{
result[0] = a;
result[1] = b;
...
case 1:
result[0] = a - 2;
break;
case 2:
result[1] = b - 2;
break;
...
}
which you would call as
int results[2];
int a;
int b;
...
doStuff( a, b, results );
Note that when we pass the array expression to the function, its type is changed from int [2] to int *. Except when it is the operand of the sizeof or unary & operators, or is a string literal used to initialize another array, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array. Array expressions in C lose their "array-ness" in most circumstances1. You can use the subscript operator [] on a pointer expression as you would an array expression (the array index operation a[i] is defined as *(a + i)), but pointers are not arrays and vice versa.
1. Note that I'm talking about the expression, not the object. The array object always stays an array object.
Simple solution (Passing by reference/pointer allows to change the value stored)
#include <stdio.h>
//alter values based on input
void doStuff(int *a, int *b, int option)
{
switch(option)
{
case 1:
// a decremented by 2, b is unchanged
*a = *a - 2;
break;
case 2:
// b decremented by 2, a is unchanged
*b = *b - 2;
break;
default:
// a and b are unchanged
break;
}
}
int main()
{
int a = 20;
int b = 20;
int option;
printf("Enter option (1 or 2):\n");
scanf("%d", &option);
printf("BEFORE doStuff() :: a = %d, b = %d\n", a, b);
doStuff(&a, &b, option);
printf("AFTER doStuff() :: a = %d, b = %d\n", a, b);
return 0;
}
You can wrap the array with a struct to return it directly.
#include <stdio.h>
struct doStuffRet {
int arr[2];
};
//alter values based on input
struct doStuffRet doStuff(int a, int b){
int option;
struct doStuffRet r = {{a, b}};
scanf("%d", &option);
switch(option) {
case 1:
r.arr[0] = a-2;
r.arr[1] = b;
return r;
break;
case 2:
r.arr[0] = a;
r.arr[1] = b-2;
return r;
break;
default:
return r;
}
}
int main(void){
int a = 20;
int b = 20;
struct doStuffRet returnedObject;
//what i need is like in c# how I can do this
returnedObject = doStuff(a, b);
a = returnedObject.arr[0];
b = returnedObject.arr[1];
printf("%d %d\n", a, b);
return 0;
}
Make the return type int *.
Create a local variable int *result = malloc(sizeof(int) * 2); and put your a and b or whatever you need to return in result.
When you call the function, assign the result to an int *.
int *res;
res = doStuff(a, b);
a = res[0];
b = res[1];
malloc allocates space for result on the heap. Its input is the number of bytes you need.
2 ints, 4 bytes per int -> 8 bytes == 2*sizeof(int)
The problem is that every time you call your function, you will keep allocating more and more space. C doesn't do garbage collection for you, so when you're done using your int *res, you should free that space by calling free(res).
Further Details:
In C#, you would initialize an array like this: int[] result = new result[2];
Have you every tried printing an array like this Console.WriteLine(myarray);. It doesn't work does it? C# I believe prints something like System.Int32[]. If you did this in Java (System.out.println(myarray);), it would print some weird number.
That number is actually the address of the array.
When you reference your array myarray, you are actually referencing the address of the array. When you do something like myarray[1], you are getting the address of myarray, adding to it 1*sizeof(int) and fetching that value.
In C, you can define arrays in the typical way: int arr[2]; which allocates space for 2 ints.
Alternatively, you can do: int *arr; which defines a pointer (or address). However, you need to tell it to allocate space for integers. As it is now, arr doesn't really point to anything. You allocate space by calling malloc: arr = malloc(2*sizeof(int)); which dynamically allocates space for 2 integers.
Now you can put stuff in your array. arr[0] = 1.
The [] is effectively doing pointer arithmetic.
arr[1] is the same as *(arr + 1)
arr + 1 is getting the address of the array and adding 1 to it. C sees that you're adding to an int * so it interprets 1 to mean 1 int (4 bytes). The * operator dereferences the address, which means it follows the pointer and gets the value stored at that address.
If printing arr gives you 0x1000, arr+1 gives you 0x1004 and * will return the int stored at 0x1004.
On to returning arrays in functions.
In C, you can't return an array like in C# (int[] function(...)), but you can return a pointer (int *function(...)), which you can use like an array (see above example).
The reason you want to use malloc is because malloc allocates space on the heap, so you can use that array after the function returns. If you defined an array like int arr[2];, the space would be allocated on the stack, and the array wouldn't persist after the function returns.
Perhaps you should look at a tutorial to learn more about pointers. I think my answer is too lengthy and not totally relevant to the question.
I'm a java student who's currently learning about pointers and C.
I tried to make a simple palindrome tester in C using a single array and pointer arithmetic.
I got it to work without a loop (example for an array of size 10 :*(test) == *(test+9) was true.
Having trouble with my loop. School me!
#include<stdio.h>
//function declaration
//int palindrome(int *test);
int main()
{
int output;
int numArray[10] = {0,2,3,4,1,1,4,3,2,0};
int *ptr;
ptr = &numArray[0];
output = palindrome(ptr);
printf("%d", output);
}
//function determine if string is a palindrome
int palindrome(int *test) {
int i;
for (i = 0; i <= (sizeof(test) / 2); i++) {
if (*(test + i) == *(test + (sizeof(test) - i)))
return 1;
else
return 0;
}
}
The Name of the array will itself acts as a pointer to an first element of the array, if you loose the pointer then there is no means for you to access the element of the array and hence you can send just the name of the array as a parameter to the function.
In the palindrome function:
you have used sizeof(test)/2. what happens is the address gets divided which is meaningless and hence you should not use that to calculate the mid element.
sizeof the pointer will be the same irrespective of the type of address that gets stored.
Why do you copy your pointer in another variable?
int *ptr;
ptr = &numArray[0];
Just send it to you function:
palindrome(numArray);
And sizeof(test) give you the memory size of a pointer, it's not what you want. You have to give the size in parameter of your function.
int palindrome(int *test, int size){
...
}
Finally your code must look like this:
#include<stdio.h>
int palindrome(int *test, int size);
int main()
{
int output;
int numArray[10] = {0,2,3,4,1,1,4,3,2,0};
output = palindrome(numArray, 10);
printf("%d", output);
}
//function determine if string is a palindrome
int palindrome(int *test, int size) {
int i;
for (i = 0; i < size / 2; i++) {
if (*(test + i) != *(test + (size - 1) - i))
return 0;
}
return 1;
}
I have a certain struct structXand a 2D array which holds these kind of structs.
I want to be able to save a pointer to that 2D struct and iterate over it
in a dynamic way, meaning, the pointer can hold any structX and iterate.
Example in general lines:
struct structX *ptr = NULL;
...
if(i == OK)
{
ptr = General_struct_which_holds_others->ptr1;
}
else if(i ==NOT_OK)
{
ptr = General_struct_which_holds_others->ptr2;
}
Now the iteration:
if(ptr[x][y] == OK) <----Error, subscripted value is neither array nor pointer
{
...
}
I hope i'm understood, As i was saying this is very general.
How can the iteration be made? meaning not getting errors?
Thanks!
Two problem I can noticce in your code if(ptr[x][y] == OK)
(1):
ptr is pointer to structure (single *) you can't use double indices [][] so error at if(ptr[x][y] == OK)
error, subscripted value is neither array nor pointer because of ptr[][]
(2):
error: used struct type value where scalar is required means if(struct are not allow).
if(should be a scalar value )
scalar value means can be convert into 0/1.
Pointer to 2D struct array C
struct structX matrix2D[ROW][COL];
its pointer
struct structX (*ptr2D)[ROW][COL];
ptr2D = &matrix2D;
ok, access you array structure like this:
struct structX i;
(*ptr2D)[r][c] = i;
If you want to pass in an function do like:
void to(struct structX* ptr2D[][COL]){
struct structX i;
ptr2D[][COL] = i;
}
void from(){
struct structX matrix2D[ROW][COL];
to(matrix2D);
}
Just to make you sure I written a simple code shows how to work with ptr2D. Hope you find it helpful:
#include<stdio.h>
#define ROW 10
#define COL 5
typedef struct {
int a;
char b;
} structX;
void to(structX ptr2D[][COL], int r, int c){
printf("in to: %d %c\n", ptr2D[r][c].a, ptr2D[r][c].b);
}
int main(){
structX matrix[ROW][COL];
structX (*ptr2D)[ROW][COL];
ptr2D = &matrix;
structX i;
i.a = 5;
i.b = 'a';
int r = 3;
int c = 2;
(*ptr2D)[r][c] = i;
printf("%d %c\n", (*ptr2D)[r][c].a, (*ptr2D)[r][c].b);
to(matrix, r, c);
}
And its working, Output:
5 a
in to: 5 a
EDIT
I wanted to show two tricks but now I think I should provide a uniform method(as you commented):
So here is the code:
#include<stdio.h>
#define ROW 10
#define COL 5
typedef struct {
int a;
char b;
} structX;
void to(structX (*ptr2D)[ROW][COL], int r, int c){
printf("in to: %d %c\n", (*ptr2D)[r][c].a, (*ptr2D)[r][c].b);
}
int main(){
structX matrix[ROW][COL];
structX (*ptr2D)[ROW][COL];
ptr2D = &matrix;
structX i;
i.a = 5;
i.b = 'a';
int r = 3;
int c = 2;
(*ptr2D)[r][c] = i;
printf("%d %c\n", (*ptr2D)[r][c].a, (*ptr2D)[r][c].b);
to(&matrix, r, c);
}
Output
5 a
in to: 5 a
EDIT:
error: used struct type value where scalar is required means if(struct are not allow).
if(should be a scalar value )
you can't do like if((*ptr2D)[r][c]);
but this is allow:
if((*ptr2D)[r][c].a == 5);
or
if((*ptr2D)[r][c].b == 'a');
or
if((*ptr2D)[r][c].a == 5 && (*ptr2D)[r][c].b == 'a');
or
structX i;
if((*ptr2D)[r][c] == i);
You might want to ready this article about multidimensional arrays. If you want to iterate over an array, you need to know how big it is (whether it is dynamic or not). If you want it to be dynamic, that means you need to allocate memory for it when it needs to grow and you need to free the old memory. You also have a problem in your question - you declare a single pointer which is null and then try to dereference it but you never allocated memory for it.
If you did allocate memory for it, you could dereference it by saying
ptr[x * ROW_WIDTH + y]
if you set ROW_WIDTH to the maximum value of y. Depending on whether you want to represent a rows major or column major array, you might use y * width instead of x * width.
This question already has answers here:
Manipulate multidimensional array in a function
(4 answers)
Closed 8 years ago.
I'm learning pointers, and gotten stuck for an hour now, with this code,
#include <stdio.h>
int determinant(int **mat) /* int mat[3][3] works fine.. int *mat[3] doesn't.. neither does int *mat[] */
{
int det;
int a=*(*(mat+0)+0); // printf("\n%d",a);
int b=*(*(mat+0)+1); // printf("\n%d",b);
int c=*(*(mat+0)+2); // printf("\n%d",c);
int d=*(*(mat+1)+0); // printf("\n%d",d);
int e=*(*(mat+1)+1); // printf("\n%d",e);
int f=*(*(mat+1)+2); // printf("\n%d",f);
int g=*(*(mat+2)+0); // printf("\n%d",g);
int h=*(*(mat+2)+1); // printf("\n%d",h);
int i=*(*(mat+2)+2); // printf("\n%d",i);
det = a*(e*i-h*f) - b*(d*i-g*f) + c*(d*h-e*g);
return det;
}
int main()
{
int mat[3][3];
int i,j;
printf("Enter the 3 X 3 matrix:\n\n");
for (i=0;i<3;i++)
{
for (j=0;j<3;j++)
{
scanf("%d",*(mat+i)+j);
}
}
printf("\nThe determinant of the given 3 X 3 matrix is %d",determinant(mat));
return 0;
}
I don't think anything is wrong with the function call. Maybe the problem is while accepting the arguments. Idk, isn't mat a pointer to an 1-dimensional array, which would again be a pointer to the array element, making mat a pointer to a pointer?
When I print some text at places (just to check), i find that the execution goes till after int det in the function, and the program crashes in the next step.
mat [3][3] works well, but i wanna use some * there, because as i said, i'm 'learning'..
Please help!
Thanks :)
The correct prototype for your function is
int determinant(int mat[][3]);
or
int determinant(int (*mat)[3]);
(both are equivalent because of a special rule for arrays as function arguments)
Then you can simply access your matrix elements with something like mat[i][j].
This is because 2 dimensional array and pointer to pointer are not same.
No matter how much dimension does an array have, its 1 dimensional in actual memory. So we can access it serially.
#include <stdio.h>
#include <conio.h>
int determinant(int *matrix1stMember)
{
int a, b, c, d, e, f, g, h, i;
a = *(matrix1stMember + 0);
b = *(matrix1stMember + 1);
c = *(matrix1stMember + 2);
d = *(matrix1stMember + 3);
e = *(matrix1stMember + 4);
f = *(matrix1stMember + 5);
g = *(matrix1stMember + 6);
h = *(matrix1stMember + 7);
i = *(matrix1stMember + 8);
return ( a*(e*i-h*f) - b*(d*i-g*f) + c*(d*h-e*g) );
}
int main()
{
int matrix[3][3]; // int matrix[y][x]; not [x][y]
int i, j;
printf("\nEnter 3x3 Matrix : ");
for(j = 0; j < 3; j++)
{
for(i = 0; i < 3; i++)
{
scanf("%d", &matrix[j][i]);
}
}
// call function determinant(int*) using first member of array
printf("\nDeterminant = %d", determinant(&matrix[0][0]));
getch();
return 0;
}
If we have to access via row and column then we can do following
data = *(_1stMemberofArray + rowIndex*totalColumn + columnIndex);
For Example,
data = matrix[2][1];
where datatype of matrix is
int matrix[3][3];
is identical to.
data = *(matrixPointer + 2*3 + 1);
where 3 is total column 2 is row(vertical or y) and 1 is column(horizontal or x).
and datatype of matrixPointer is,
int* matrixPointer;
and it should point to first member of matrix;
2D array dont decay to pointer to pointer. You can decay them to pointers so your code should look like
int determinant(int *mat) {
int det;
int a=*((mat+0)+0); // printf("\n%d",a);
int b=*((mat+0)+1); // printf("\n%d",b);
int c=*((mat+0)+2); // printf("\n%d",c);
int d=*((mat+1*3)+0); // printf("\n%d",d);
int e=*((mat+1*3)+1); // printf("\n%d",e);
int f=*((mat+1*3)+2); // printf("\n%d",f);
int g=*((mat+2*3)+0); // printf("\n%d",g);
int h=*((mat+2*3)+1); // printf("\n%d",h);
int i=*((mat+2*3)+2); // printf("\n%d",i);
det = a*(e*i-h*f) - b*(d*i-g*f) + c*(d*h-e*g);
return det;
}
The above code is just for illustration, showing how 2-D array decays to 1-D array.
When you try to access the array using braces like a[2][1] then compiler does is unfolding for you. By unfolding I mean, the multiplication by sizeof(type) (as shown above multiply by 3). So if you decaying to 1-D you have to do it yourself.
One more thing to add, always pass the size of the dimension to the function who is has to tread the 1-D array as 2-D. like
int determinant(int *mat, int cols, rows);
Edit 1:
Just to add that #JensGustedt ans is also ok if you want to keep the arrays intact across function calls.
The correct signature for the function would be
int determinant(int mat[][3])
or
int determinant(int (*mat)[3])
In the context of a function parameter declaration, T a[] and T *a are exactly equivalent.
With either option, you can subscript mat normally in the function as you would in main:
int a = mat[0][0];
int b = mat[0][1];
...
Since a subscript operation implicitly dereferences the pointer (a[i] == *(a + i)),
you don't have to do the explicit dereference dance, making your code easier to read and understand (and potentially faster; I've seen some compilers generate more instructions for *(*(a + i) + j) than a[i][j], but don't rely on that being true everywhere).
Remember that when an expression of "N-element array of T" appears in most contexts, it is converted to an expression of type "pointer to T" and its value is the address of the first element in the array. Since the expression mat in the call to printf has type "3-element array of 3-element arrays of int", it is replaced with an expression of type "pointer to 3-element array of int".
If we pass a multidimensional array to a function:
int a2[5][7];
func(a2);
We can not declare that function as accepting a pointer-to-pointer
func(int **a) /* WRONG */
{
...
}
The function ends up receiving a pointer-to-an-array, not a pointer-to-a-pointer.