about multi dimensional in c language [duplicate] - c

This question already has answers here:
Initializing a 2D array like a 1D array
(3 answers)
Closed 5 years ago.
If the array is initialized like this:
int a[4][3]={1,2,3,4,5,6,7,8,9};
Could someone please help me how the elements are stored in array indices, like a[0][0] will be which element and so on

Statement:
int a[4][3]={1,2,3,4,5,6,7,8,9};
is equivalent to:
int a[4][3] = {
{1,2,3}, //every row contains 3 element because second dimension is 3
{4,5,6},
{7,8,9}
};
With this way of representation, you can easily identify the value at a particular location in the given array.
a[0][0] will be which element and so on
a[0] is {1,2,3} and in this array the element at 0th location is 1. So,
a[0][0] is 1, Similarly
a[0][1] is 2
a[0][2] is 3
a[1][0] is 4
and so on.
May you write a program for better understanding, like this:
#include <stdio.h>
int main() {
int a[4][3]={1,2,3,4,5,6,7,8,9};
int i,j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 3; j++) {
printf ("a[%d][%d] : %d\n", i, j, a[i][j]);
}
}
return 0;
}
The output of this program is:
a[0][0] : 1
a[0][1] : 2
a[0][2] : 3
a[1][0] : 4
a[1][1] : 5
a[1][2] : 6
a[2][0] : 7
a[2][1] : 8
a[2][2] : 9
a[3][0] : 0
a[3][1] : 0
a[3][2] : 0
Here you can see the last row (a[3]) is having all elements value 0. This is because in array initialization if there are fewer initializers than elements in the array then, remaining elements are automatically initialized to 0. Since you are providing only 3 rows in the initialization of the array of 4 rows, the elements of the last row will be initialized with 0.
The array a is:
1 2 3
4 5 6
7 8 9
0 0 0

A multi-dimensional array store arrays.Suppose you have arr[4][3],this means that that array "arr" is consist of 4 arrays, each of length you specified in the second bracket.
Also in order to assign multi-dimensional array you should do it like this
int arr[size1][size2] = {{contents of first},{content of second},{content of third},{etc}};
arr[0][0] will contain element located at first index of first array

mapping multi-dimensional data on it can be done in several ways. there are mainly two types of data store procedure in 2D Array.
1.Row Major
Computer memory will be represented as a linear array with low addresses on the left and high addresses on the right. Also, we're going to use programmer notation for matrices: rows and columns start with zero, at the top-left corner of the matrix. Row indices go over rows from top to bottom; column indices go over columns from left to right.
As mentioned above, in row-major layout, the first row of the matrix is placed in contiguous memory, then the second, and so on.
Image of Row Major :-- Click Below
Array & Memory Representation of Storing Data in 2D Array by Row Major
2.Column Major
Describing column-major 2D layout is just taking the description of row-major and replacing every appearance of "row" by "column" and vice versa. The first column of the matrix is placed in contiguous memory, then the second, and so on:
Image of Column Major:--- Click Below
Array & Memory Representation of Storing Data in 2D Array by Column Major
I hope this will help you to understand how the value stored in araay.

Related

Why is the Index NOT out of bounds although it intuitively should?

I'm relatively new to C programming and I stumbled upon a for me unexplainable behaviour while running the following code and debugging it using gdb and lldb.
In short: When swapping the indices i and j (max i != max j) when accessing a value in a two-dimensional Array inside a double nested for-loop it does not seem to matter if I access the value using array[i][j] or array[j][i].
The two loops and arrays are mostly identical.
unsigned matrix[3][1] =
{
{3},
{4},
{5}
};
//Loop1
for (size_t i = 0; i < sizeof(matrix) / sizeof(*matrix); i++)
{
for (size_t j = 0; j < sizeof(matrix[i]) / sizeof(*matrix[i]); j++)
{
matrix[i][j] <<= 1;
printf("matrix[%zu][%zu] has the value: %d\n", i, j, matrix[i][j]);
}
}
//same two dimensional array as matrix
unsigned matrix2[3][1] =
{
{3},
{4},
{5}
};
//Loop2, basically the same loop as Loop1
for (size_t i = 0; i < sizeof(matrix2) / sizeof(*matrix2); i++)
{
for (size_t j = 0; j < sizeof(matrix2[i]) / sizeof(*matrix2[i]); j++)
{
//swapped i and j here
matrix2[j][i] <<= 1;
printf("matrix2[%zu][%zu] has the value: %d\n", j, i, matrix2[j][i]);
}
}
Am I missing here something?
In both cases i is passed the value 2 at the end of the outer loop and j the value 0 at the end of the inner loop.
Intuitively, matrix[0][2] should throw an exception as each row only has one element.
I will take a slightly different approach than the other respondents.
You are technically not reading outside of the array's boundary as far as the memory layout is concerned. Looking at it from a human perspective you are (the index [0][2] doesn't exist!), but the memory layout of the array is contiguous. Each of the "rows" of the matrix are stored next to each other.
In memory, your array is stored as: | ? | 3 | 4 | 5 | ? |
So when you index to matrix[1][0] or matrix [0][1] you are accessing the same position in memory. This would not be the case if your array was larger than 1 dimension wide.
For example, replace your array with the following one and experiment. You can access integer '4' either by indexing matrix[0][2], or matrix [1][0]. The position [0][2] shouldn't exist, but it does because the memory is contiguous.
unsigned matrix[3][2] =
{
{3, 6},
{4, 8},
{5, 10}
};
Oops, matrix[0][2] should throw an exception as each row only has one element...
Some languages do warn the programmer by an exception if they try an out of bound access, but C does not. It just invokes Undefined Behaviour. On a technical point of view, it means that the compiler does not have to test the out of bound condition. On an operational point of view, it means that anything can happen, including expected behaviour... or an immediate crash... or a modification of an unrelated variable... or...
If my C skills aren't mega-rusty you're reading "unsafe memory".
Essentially your matrix is declared as a block of bytes. After that block of bytes there are more bytes. What are they? Usually more variables that are declared as your program's data. Once you reach the end of the program's data block you reach the user code memory block (encoded ASM instructions).
Most languages perform checks and throw an exception when you run out of bounds by somehow keeping track of the last index that is valid to access. C does not do that and doing such thing is your very own responsibility. If you aren't careful you might be overwriting important parts of your program's code.
There are attacks that one can perform on C programs that don't sanitize user input, like a buffer overrun; which exploits what it's been described.
Essentially if you declare a char[] of length N and store a string that comes from outside and this string happens to be of length N+X you'll be overwriting program memory (instructions).
With the right sequence of characters you can inject your very own assembly code into a running program which doesn't sanitize user input
As your array is int and all elements are of the same size, i don't see any problem as your array is stored in contiguous space in RAM and you use a special case of matrix where inverting indexes has no side effect.
In the first loop your indexes are [0][0], [1][0], [2][0]
In the second loop your indexes are [0][0], [0][1], [0][2]
now try to linear the access, as your array is saved as linear array into the RAM.
address of element = row * NCOL + col
row: is row number
NCOL: number of columns into your matrix
col : the column number
so the linear index for :
[0][2] ==> 0 * 1 + 2 = 2 /* the third element*/
[2][0] ==> 2 * 1 + 0 = 2 /* always the third element */
But if you use a matrix of n x m , n >= 1 and m > 1 and n != m.
if you inverse the indexes, the result will not be the same.
so if you take a 4 x 2 matrix
linear index of [3][1] = 3 * 2 + 1 = 7
linear index of [1][3] = 1 * 2 + 3 = 5 /* even [1][3] is out of the range of your matrix index */
[1][3] you will manipulate the element [2][1]
So be worry when manipulating matrix indexes.

Finding 2D array cell memory location

There is an array a[3][4] and we have to find the address of a[2][2] using row major order and 1001 as base address. I found 2 formulas do find the address:
For any array a[M][N] Row Major Order:
1) a[i][j] = Base Address+Datatype Size[(N*i)+j]
2) a[i][j] = Base Address+Datatype Size[N*(i-1)+(j-1)]
I tried both the formulas but the first one yielded the correct result but not the second one. Here is how I found the address of a[2][2] using row major order:
Using Formula 1:
a[2][2] = 1001+2[(4*2)+2]
= 1001+2[10]
= 1001+20
= 1021 (correct answer)
Using Formula 2:
a[2][2] = 1001+2[4*(2-1)+(2-1)]
= 1001+2[4+1]
= 1001+2[5]
= 1001+10
= 1011 (Wrong Answer)
Is there any error in my 2nd formula or have I done something wrong in the calculation using 2nd formula? Why aren't both the answers coming same?
as amit said, the equations are different, so they are not going to give the same result. when ever in doubt about a problem like this, try putting some numbers in the equations and try them out, so if we are trying for an array of size 4, at position 2,2
equation 1: (N * i) + j, (4 * 2) + 2 = 10
equation 2: N * (I - 1) + (j - 1) = 9
as you can see as they are not the same result, the problem is not in your code, but in the equation itself
if you are feeling brave, you can also try and prove it by induction as well
To find the memory address number, you will also need to know how much space an integer is occupying in memory as well. You can do this with sizeof(int);which will output how many bytes the integer is using on the system.
you will also need to know how an array of arrays is formatted in memory. Just like a normal array, and array of arrays is contiguous, meaning that there are no gaps in memory between the array elements. So an array a[2][2] {1,2}, {3,4} would be formatted like this. 1, 2, 3, 4.
using this you should be able to find the memory location with the following equation address location of array a[I][j] = B + W * [N * (I- Lr) + (J - Lc)] where:
B is the base address
I is the row subscript of the element you are looking for
J is the column element you are looking for
W is the size of an element
Lr is the lower limit of a row - 0 if not given
Lc is the lower limit of a column - 0 if not given
M is the number of rows of the matrix
N is the number of columns of the matrix

pointer and multidimensional array

i want to print the value which contain in the multidimensional array.I know that if we write something like arr[3][4] then arr[0] is the pointer to the first element in the that multidimensional array.
I want to ask why this code give me garbage value after the program print the number containing in the multidimensional array?
this is the code:
#include <stdio.h>
#define ROW 3
#define COLL 4
int main(void) {
int arr[ROW][COLL]={{1,2,3,4},
{5,6,7,8},
{9,10,11,12}};
int *ptr;
for(ptr=arr[0];ptr<arr[ROW]+COLL;ptr++){
printf("%d ",*ptr);
}
printf("\n");
return 0;
}
this is the result when i compile the above code:
1 2 3 4 5 6 7 8 9 10 11 12 -1079481492 134513936 0 -1079481352
but after changing the for loop to the following:
for(ptr=arr[0];ptr<=arr[ROW-1]+COLL-1;ptr++)
the code work and give the exact number which contain in the multidimensional array.
Because arr[ROW] is an out-of-bounds access. The last valid position in arr is arr[ROW-1]. Thus the first version of your code invokes undefined behaviour.
The pointer to the last element is
arr[ROW-1] + COLL - 1
So you loop should be
for (ptr = arr; ptr < arr[ROW-1] + COLL; ptr++) {
Elements of an array are indexed from 0 so the last element in your matrix is arr[ROW-1][COLL-1].
When your pointer reaches arr[2] + COLL there is no such element because the second coordinate of the last element in last row is [COLL-1].
Elements of an array are stored in 1D so arr[0] + 4 is acctualy arr[1][0].
When you increment ptr++ it tells the compiler to access the next memory location after the current. So, when ptr points to a[0] + 4 it works because the compiler access the fifth value after a[0][0] which is actually the first value in the next row, arr[1][0], because their memory locations are next to each other.
When your ptr points to arr[4] + i, i = 0, 1, 2, 3 you get bad output because those elements are not in your array.
Because your first element, 1, is at arr[0]+0,
5 is at arr[1]+0,
9 is at arr[2]+0,
10 is at arr[2]+1,
11 is at arr[2]+2,
and 12, which is the last element of your array is at arr[2]+3.
but your for loop keeps moving even after the array ends, that is, until the memory location arr[3]+4 is reached. Giving you four garbage values because we have stored nothing in the memory after arr[2]+3.
so the for loop should be like:
for (ptr=arr; ptr <= arr[ROW-1]+COLL-1; ptr++);
which is equivalent to:
for (ptr=arr[0]; ptr <= arr[ROW-1]+COLL-1; ptr++);
as arr[0] and arr point to the same location in memory.
NOTE- try reading how memory is allocated in arrays of multiple dimensions.

How does accessing a 2D array in C with 1 dimension work

I'm trying to understand some C code and I can't wrap my head around the following issues:
Why does printing an array by accessing it with 1 dimension reverse the order the values in which the stored values print?
If the array was declared as a [3][4] array, is it possible to reference a value at array[3][x]?
The author initializes a 2d array - word[3][4], which based on my understanding creates a 3 row/4 column array in memory-
Col 0 Col 1 Col 2 Col 3
Row 0 [0][0] [0][1] [0][2] [0][3]
Row 1 [1][0] [1][1] [1][2] [1][3]
Row 2 [2][0] [2][1] [2][2] [2][3]
Later, values are written to the array hardcoding the row and changing the column based on a loop control valriable, z, going from 0-3:
word[0][z]
word[1][z]
word[2][z]
word[3][z]
At the end, the array is displayed by referencing one dimension:
printf("%x", *((unsigned int *)word[i]));
This appears to print the values stored in memory in reverse:
75757575
42424242
48484849
even though they are held in memory as shown below:
0xbfa33050: 75757575
0xbfa33054: 42424242
0xbfa33058: 49484848
Thoughts?
According to the standard elements of an array are contiguous in memory (this is the main property of array). So any array no matter what it's dimension has the same representation in memory, using multiply indexes - is syntactic sugar.
C stores arrays in row major order, with row 0 first, then row 1, and so forth. This image may help you to understand it in a more clear way
Why does printing an array by accessing it with 1 dimension reverse
the order the values in which the stored values print?
Because they are stored in contiguous in memory.
If the array was declared as a [2][3] array, is it possible to
reference a 4th row when only 3 were declared?
If you do so, you are trying to access out of bound elements.
This appears to print the values stored in memory in reverse-
Because that's how it is stored in stack!
For more details you can refer this image
I'm afraid you're conflating two different issues: array subscripting and endianism.
Take the code
int a[2][3] = { 0,1,2,3,4,5,6 };
The value at a[x][y] is the value at a[x*3+y].
The value at a[1][2] is the value at a[5] = 5. [Assuming I didn't make any mistakes!]
The apparent reversal of order in memory is because the Intel processor is little endian, so it puts the little end (low byte) of the number first. The memory layout looks like this:
00000000
01000000
02000000
03000000
etc
That has nothing to do with arrays.

Scanning values into a matrix without using [ ] C language

I have a problem. I was asked to write a program that transposes a matrix, without using []...for example, i know that if it was a one dimensional array, i could say that array[3] is the same as *(array+3)...but how do i do that with a matrix?
here's my code for scanning:
void scan_matrix(matrix mat1,int number_of_rows, int number_of_columns)
{
int row_index,column_index;
for(row_index=0;row_index<number_of_rows;row_index++)
{
printf("Enter the values of row %d\n",row_index);
for(column_index=0;column_index<number_of_columns;column_index++)
scanf("%d",WHAT GOES HERE?????);
}
}
If mat1 is a simple pointer, then this should do the job for you :
for(row_index=0;row_index<number_of_rows;row_index++)
{
printf("Enter the values of row %d\n",row_index);
for(column_index=0;column_index<number_of_columns;column_index++)
scanf("%d", (mat1 + row_index*number_of_columns + column_index));
}
The program uses the fact that matrices (2-d arrays) are in fact stored as 1-dimensional arrays in memory.
Lets take a 2d matrix :
1 2 3
4 5 6
This is stored in memory as :
1 2 3 4 5 6
So, the correct variable is accessed by using a way to map the logical positions of array elements with the actual positions. All we need is to find out the relation which turns out to be :
Pos = Row*Num_Of_Col + Col
if mat is two dimensional int array like : mat[3][3]
then scanf code would be : scanf("%d",(*(mat+row_index)+column_index));
a[3] : *(a+3)
a[3][3] : (*(a+3)+3)

Resources