Converting multidimensional arrays to pointer notation [duplicate] - c

This question already has answers here:
Pointer address in a C multidimensional array
(5 answers)
Closed 2 years ago.
For the following value-of an array, I can do:
array[i][j][k] = *(*(*(array+i)+j)+k);
---------------------------------
int xar[3] = {1,2,3};
printf("%d | %d\n", xar[1], *(xar+1));
int xar2[2][3] = {{1,2,3}, {4,5,6}};
printf("%d | %d\n", xar2[1][2], *(*(xar2+1)+2));
int xar3[2][2][2] = {
{{1, 2},{3, 4}},
{{5, 6}, {7, 8}}
};
printf("%d | %d\n", xar3[1][1][1], *(*(*(xar3+1)+1)+1));
2 | 2
6 | 6
8 | 8
However, I'm having a tougher time trying to get the address of an array element and why that works, for example, if I have:
&array[i][j][k];
array+i gives me the equivalent of &array[i], but then how would I grab the full inner item?

Note that &*array will cancel each-other out, so we can do:
array[i][j][k] = *(*(*(array+i)+j)+k);
&array[i][j][k] = &*(*(*(array+i)+j)+k); // &* can be eliminated
&array[i][j][k] = *(*(array+i)+j)+k;

Related

Is it possible to declare an immutable Array and assign value to its elements separately in Rust [duplicate]

This question already has answers here:
Is there a more idiomatic way to initialize an array with random numbers than a for loop?
(2 answers)
What is the proper way to initialize a fixed length array?
(3 answers)
How do I generate a vector of random numbers in a range?
(2 answers)
Closed 3 years ago.
I want to declare an Array and want to initialize it like this
(maybe it is not good in real development, but I just want to figure it out)
the key point is that: 1. h is immutable 2. assign(also initialize) h[0] h[1] and h[2] separately.
use std::thread;
use std::time::Duration;
use rand::Rng; // 0.6.5
fn main() {
loop {
let h: [u32; 3];
h[0] = rand::thread_rng().gen_range(1, 101);
h[1] = rand::thread_rng().gen_range(1, 101);
h[2] = rand::thread_rng().gen_range(1, 101);
println!("{:?}", h);
thread::sleep(Duration::from_secs(2));
}
}
but the compiler says that
error[E0381]: use of possibly uninitialized variable: `h`
--> src\main.rs:11:9
|
11 | h[0] = rand::thread_rng().gen_range(1, 101);
| ^^^^ use of possibly uninitialized `h`
error: aborting due to previous error
of course h is uninitialized here, so what could I do?
or it is impossible to do such a thing

function to zero array elements

I wrote this code that check suduko answers and for some reason my the array which I sum the squares of the suduko into is all zeros in the functions I zero it in, but when I use it in my check function it isn't all zeros
if i move the exact same code of my array zeroing function to my other function and run it it works.
(i am using c99, dont know if it matters)
Any ideas?
int squareSum[5][5];
//set array elements to zero
setArrayToZero(squareSize, squareSize, squareSum);
/*for(int i = 0; i<squareSize; i++){
for(int j = 0; j<squareSize; j++)
squareSum[i][j] = 0;
}*/
printf("%d, %d\n%d, %d\n\n", squareSum[0][0], squareSum[0][1], squareSum[1][0], squareSum[1][1]);
this is the array is case squareSize is two
if i add the for in the comments in, the array isall zeros, and as you can see below its the exact same as the function i call.
void setArrayToZero(int rows, int columns, int array[][columns]){
for(int i = 0; i<rows; i++)
for(int j = 0; j<columns; j++)
array[i][j] = 0;\\if i print the array in function its all zeros.
p.s
i know i am using only part of the array, its an assignment from the university and we are not allowed to use malloc so i am creating the array at thier max size - 25.
thank you in advance.
full c file:
https://drive.google.com/open?id=1L00L3lvMYNcaz2SswEBnmi9KO-79oaHg
all the print functions, are part of the demand for the course (for auto checking)
A reference to an object of type array-of-T which appears in an
expression decays (with three exceptions) into a pointer to its first
element; the type of the resultant pointer is pointer-to-T.
So that means in this case also (this is not one of those 3 exceptions) your passed array will decay into pointers and now you change to the array by accessing the address, that's why it will be retained in the callee function.
You are doing it the right way. The problem is not with passing or anything. Maybe you are accessing it wrong or maybe you didn't initialize it properly. But there is nothing wrong with the zeroing out.
And for further information everything is pass by value in C. There is nothing called pass by reference in C. The pointer workings makes us think that there is something called pass by reference in C but that's not the case, here also pointer variables are copied into some local variable in the called function. but as we have those addresses in the called function and we access them and make changes - they retain in callee function.
After OP posted the sample code
Apaprt from the overly complicated sudoku checking logic there is much more going wrong.
I will just mention the printing part.
In C elements of 2d-arrays are stored sequentially. When we pass the 2d array to the function we need to specify the column size so that we can determine the correct element.
Suppose you want to access a[4][7] in 10x13 array. The element would be at the address &a[0][0]+4*13+7. That's why the column part is passed as an argument.
Now what you did :
int squareSum[5][5], rowColSum[25][2];
//set arrays elements to zero
setArrayToZero(size, 2, rowColSum);
setArrayToZero(squareSize, squareSize, squareSum);
The first one is alright. As there are 2 columns. But what about the second one?
here you are telling the function that you are passing an array with column size = 2 but that is not the case. It is still the 2d array with 5 columns.
That's where you had the problem. Suppose you initialize the array with 10,21,34,14
Suppose grid is 5x5 array (in your case it's 25x25)
grid[5][5] array
And you do this
for(int i = 0; i<squareSize; i++)
for(int j = 0; j<squareSize; j++)
scanf("%d",&grid[i][j]);
/*
Input is 13 17 19 23
*/
+-----+-----+-----+------+-----+-----+-----+----+----+----+--...\
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+-----+-----+-----+------+-----+-----+-----+----+----+----+--...\
/ \ \ / \ \
13 17 19 23
Now you access it like this
You pass it to the function with this call print2dArray(int row, int col, int g[][col])
You call like this `print2dArray(2,2,grid);``
...
for(int i = 0; i<row; i++)
for(int j = 0; j<col; j++)
printf("%d",&grid[i][j]);
Now you will print these elements (i) : denotes the order
+-----+-----+-----+------+-----+-----+-----+----+----+----+--...\
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+-----+-----+-----+------+-----+-----+-----+----+----+----+--...\
/ \ \ ^ ^ / \ \
13 17 | | 19 23
(1) (2) (3) (4)
Similarly, those were uninitialized in your case. That's why you got those weird results. You were initializing some elements of the 2d array to 0 but when you are reading the array then you were accessing some different elements. That's why the wrong result.
Solution for this:
Call int correctSum = inputGrid(squareSize, 25, grid); Note that it should be squareSize. Accordingly change the storage of digitsCounter in inputGrid.
The function signature for inputGrid would be inputGrid(size, col, grid[][col]);
Same when calling the
setArrayToZero(size, 2, rowColSum); and
setArrayToZero(squareSize, 5, squareSum);
I simply didn't check the logic. The answer deals with explaining the printing behavior of the 2d array.

How does `*((*arr+(i*3))+j)` work when printing a 2D array `arr`?

Code:
#include <stdio.h>
int main(void)
{
int arr[2][3] = {{1,2,3},{4,5,6}};
int i, j;
for(i = 0; i < 2; i++)
{
for(j = 0; j < 3; j++)
{
printf("%d ", *((*arr+(i*3))+j));
}
printf("\n");
}
return 0;
}
I'm surprised how the above code gives the output:
1 2 3
4 5 6
I know that *(arr+i) == arr[i] and also that I should be using arr[i][j] instead of making everything more complicated, but I don't understand how *((*arr+(i*3))+j) works.
In my understanding, *((*arr+(i*3))+j) can be simplified to *((*arr)+(i*3)+j) since the *(indirection operator) has the most precedence here.
So, when i is zero and j iterates through, 0 to 2, the expression is the same as arr[0][j] which prints the integers of the first subarray.
My confusion builds up when i becomes 1. The next three expressions will be *((*arr)+(1*3)+0), *((*arr)+(1*3)+1) and *((*arr)+(1*3)+2) which can be simplified to arr[0][3], arr[0][4] and arr[0][5].
How does this print the last three values?
int arr[2][3] = {{1,2,3},{4,5,6}};
In memory :
1 | 2 | 3 | 4 | 5 | 6
each number on an adjacent memory "cell" the size of an int, in this order
Second line :
i = 1
j = 0
*((*arr+(i*3))+j)) means *((*arr + 3) + 0)-> *({1, 2, 3} + 3) -> *({4, 5, 6}) = 4
Keep in mind that x[n] is equivalent to *(x + n), whatever x or n. (This also means arr[1] is equivalent to *(arr + 1), *(1 + arr) and so 1[arr] which I find funny)
Here arr[1][0] : x is arr[1] and n is 0 so first equivalence: *(arr[1] + 0)
Second x is arr and n is 1 so *(*(arr + 1) + 0).
Finally arr + 1 means the adress at arr + sizeof(*arr), which means:
(arr + 1) is equivalent to (*arr + 3) because *arr is arr[0] which is of type int[3]
The C language stores multidimensional arrays in what is called row-major order,
so when you declare int arr[2][3] the memory is actually laid out with the entries of the array occurring adjacent to each other in
memory in this sequence:
arr[0][0] arr[0][1] arr[0][2] arr[1][0] arr[1][1] arr[1][2]
This has a couple of consequences that are useful to know:
arr[1] acts like a pointer to a one-dimensional array. just as it does when you declare int **arr;.
The initializers in your initialization list are copied into memory locations in exactly the order you list them.
The array is stored in your memory like :
_____ _____ _____ _____ _____ _____
| 1 | | 2 | | 3 | | 4 | | 5 | | 6 |
----- ----- ----- ----- ----- -----
So even though it is stored in a two dimensional array it is contagiously allocated memory during compilation. When you write a[1][1] the compiler accesses the (1*(no of columns) + 1 ) position from front i.e. the 4 position from start.
See http://www.fredosaurus.com/notes-cpp/arrayptr/23two-dim-array-memory-layout.html

output of p[-2] in C array [duplicate]

This question already has answers here:
What does s[-1] = 0 mean?
(6 answers)
Closed 8 years ago.
I was trying the below code snippet. Please help me in understanding how the o/p is coming as 2? What does p[-2] mean here?
int main(void){
int ary[4] = {1, 2, 3, 6};
int *p = ary + 3;
printf("%d\n", p[-2]);
}
ary is an array of four ints. This will be put in memory like this:
| 1 | 2 | 3 | 6 |
^ ^ ^
| | |
ary p - 2 p
By saying p = ary + 3, you're setting p to the address of the fourth element in the array. So, p is pointing to 6. p[-2] is equal to *(p - 2). That means you point p to the second element in the array, and access its value: 2.
int *p = ary + 3 points to ary[3] so if you move the pointer two steps back you will get ary[1]

i need a brief and simple understable advice to understand this code process

I am now learning the pointer and memory section of C. Now I am stuck on this code. I am not understanding how this code process and how the code shows result contestants[2] = 2. Please consider me as a very new learner and answer briefly how a single code worked and how's the result 2?
#include <stdio.h>
int main()
{
int contestants[] = {1, 2, 3};
int *choice = contestants;
contestants[0] = 2;
contestants[1] = contestants[2];
contestants[2] = *choice;
printf("I'm going to pick contestant number %i\n", contestants[2]); return 0;
}
int contestants[] = {1, 2, 3};
contestants is an array of integrs, indexed starting at 0, with values contestants[0] == 1, contestants[1] == 2 and `contestants[2] = 3.
int *choice = contestants;
choice is an integer pointer, assigned here to the address of the contestants array, which is the address of the first element of the contestants array. Therefore, *choice will give you the same result as contestants[0].
contestants[0] = 2;
This assigns 2 to contestants[0]. Now contestants[0] == 2 and, therefore, *choice == 2. The contestants array now looks like {2, 2, 3}.
contestants[1] = contestants[2];
Assigns the value 2 to contestants[1]. Now the contestants array looks like {2, 3, 3}.
contestants[2] = *choice;
Assigns *choice which is still the same as contestants[0] to contestants[2]. So the contestants array looks like {2, 3, 2}.
printf("I'm going to pick contestant number %i\n", contestants[2]); return 0;
Prints contestants[2], which is 2 as you observed.
contestants is an array of type integers which contains values {1, 2, 3}.
choice is a pointer of type int pointing to valid memory location of contestants.
Each element in array contestants are accessed as contestants[i], where i is index of array starting from 0. contestants[0] = 2; is what assigning value 2 to index location 0.
contestants[2] = *choice; - choice is a pointer, *choice is called dereferencing pointer to get the value pointing by pointer choice which is 2.
Typical memory layout is as follows,
contestants[]
choice 0 1 2
+-----+ +-------------------+
|0x100|------>| 1 | 2 | 3 |
| | | | | |
+-----+ +-------------------+
0x100 0x104 0x108

Resources