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

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.

Related

How to insert an element starting the iteration from the beginning of the array in c?

I have seen insertion of element in array starting iteration from the rear end. But i wonder if it is possible to insert from the front
I finally figured out a way, Here goes the code
#include <stdio.h>
int main()
{
int number = 5; //element to be inserted
int array[10] = {1, 2, 3, 4, 6, 7, 8, 9};
int ele, temp;
int pos = 4; // position to insert
printf("Array before insertion:\n");
for (int i = 0; i < 10; i++)
{
printf("%d ", array[i]);
}
puts("");
for (int i = pos; i < 10; i++)
{
if (i == pos) // first element
{
ele = array[i + 1];
array[i + 1] = array[i];
}
else // rest of the elements
{
temp = array[i + 1];
array[i + 1] = ele;
ele = temp;
}
}
array[pos] = number; // element to be inserted
printf("Array after insertion:\n");
for (int i = 0; i < 10; i++)
{
printf("%d ", array[i]);
}
return 0;
}
The output looks like:
Array before insertion:
1 2 3 4 6 7 8 9 0 0
Array after insertion:
1 2 3 4 5 6 7 8 9 0
In C the arrays have a "native" built-in implementation based upon the address (aka pointer) to the first element and a the [] operator for element addressing.
Once an array has been allocated, its actual size is not automatically handled or checked: the code needs to make sure boundaries are not trespassed.
Moreover, in C there is no default (aka empty) value for any variable, there included arrays and array element.
Still, in C there's no such a thing like insertion, appending or removal of an array element. You can simply refer to the n-th (with n starting at 0) array element by using the [] operator.
So, if you have an array, you cannot insert a new item at its n-th position. You can only read or (over)write any of its items.
Any other operation, like inserting or removing, requires ad-hoc code which basically boils down to shifting the arrays elements forward (for making room for insertion) or backward (for removing one).
This is the C-language nature and should not be seen as a limitation: any other language allowing for those array operations must have a lower-level hidden implementation or a non-trivial data structure to implement the arrays.
This means, in C, that while keeping the memory usage to a bare minimum, those array operations require some time-consuming implementation, like the item-shifting one.
You can then trade-off the memory usage against the time usage and get some gains in overall efficiency by using, for example, single- and double-linked lists. You loose some memory for link pointer(s) in favor of faster insertion ad removal operations. This depends mostly upon the implementation goals.
Finally, to get to the original question, an actual answer requires some extra details about the memory vs time trade off that can be done to achieve the goal.
The solution depicted by #Krishna Acharya is a simple shift-based solution with no boundary check. A very simple and somehow naive implementation.
A final note. The 0s shown by Krishna's code at the end of the arrays should be considered merely random values. As I said earlier, there is no default value.
The code should have been instead:
int array[10] = {1, 2, 3, 4, 6, 7, 8, 9, 0, 0};
in order to make sure that any unused value was 0 for the last two array elements.

I am not sure how the array of the code is being traced?

I don't understand how the array is being traced. I feel like I know it but then I mess it up again. I get how the values are being swapped but I am still getting confused. I wrote my questions as comments besides my code. Can someone help me trace that part?
#include <stdio.h>
int main()
{
int a[5]={1,2,3,4,5};
int i,j,temp;
for (j=1; j<5; j++)
for (i=0; i<5-j; i=i+2)
{
printf("%d %d\n",i,i+j); //I got this part right
temp = a[i]; //from here I get confused
a[i] = a[i+j]; //how is the addition inside working??
a[i+j] = temp; //temp = the index's value
}
for (i=0; i<5; i++)
printf("a[%d] = %d\n",i,a[i]);//what is i supposed to be here??
}
Output:
0 1
2 3
0 2
2 4
0 3
0 4
a[0] = 2 //from here on I get lost
a[1] = 1
a[2] = 5
a[3] = 4
a[4] = 3
Why don't you print your whole array in every loop, that way you can see how values are moving, for example in step in you swap 0,1 element so array is {2,1,3,4,5}, then 2,3 so {2,1,4,3,5}, then 0,2 so {4,1,2,3,5} , 2,4,=> {4,1,5,3,2}, 0,3 {3,1,5,4,2},0 4 {2,1,5,4,3}
I am guessing you don't know much about C programming. So here is a bit about arrays:
An array (here: int a[5]={1,2,3,4,5}) is contiguously allocated blocks of memory.
An array a[n] is of size 'n'(stores n values of array type, here int) and is index from 0 to n-1. Meaning each of the n values are accessed from a[0] to a[n-1].
There are multi-dimensional arrays (read it up!).
The logic given here:
temp = a[i]; //temp gets a[i]'s value and not the value of i
a[i] = a[i+j];
a[i+j] = temp;
This is the standard swap(a,b) operation using a temporary variable temp. Just that 'a' and 'b' here are elements of an array.
The loops are designed in such a way to access different elements of the array in each iteration. This shuffles the array.
So obviously:
printf("a[%d] = %d\n",i,a[i]); // i here is the index used to access a's ith element
I found out what I was doing wrong. I was simply trying to do the math and change that position's value. I have to open up space and move the old number out to put the new number in. Then the old number will go to empty space that's left. It's actually just simply swapping but it helps to see it this way better.
So in {1,2,3,4,5}, if I try to put a[3]=4 in a[1]=2, the value 4 will go to a[1].
a[1] which had 2 will have to get out and a[3] which had 4 will move in.
The 2 that was out will go in the place where 4 was before in a[3]=2.
So now a[1]=4 and a[3]=2.
So the swapped array will now look like {1,4,3,2,5}

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

"C" i couldnt understand how i can add two matrises

I'm a begginer about c and i need help about it please help
{
int matris[2][2];
for(int i=0;i<2;i++)
{
for(int j=0;j<4;j++)
{
printf("Sayi giriniz: "); scanf("%d",&matris[i][j]);
}
}
for(int i=0;i<3;i++)
{
for(int j=0;j<2;j++)
{
printf("%d ",matris[i][j]);
}
printf("\n");
}
}
As a beginner, you need to realize that programming is nothing more than problem-solving, well there is the bit about expressing the answer in a programming language.
Doing matrix addition -- how do you do it, how would a mathematician define it? Arnaldo has given you the answer to this, $A + B = C$ where $c_{ij} = a_{ij} + b_{ij}$. So already, this starts to set some restrictions on the two matrices that your are working with, notably they have to have the same number of rows and columns.
Representation of matrices -- ok, now that you know how to add to matrices, you need to figure out how you are going to represent a matrix in your program. Computer memory is a one-dimensional array of storage units, so we need to map our two dimensional structure onto this one-dimensional array. There are two ways of doing this. The first is row major which means that we write the first row to memory, then the second row and so on. The second is column major which means that we write the first column to memory and then the second row.
Consider the following 2x3 matrix:
| a b c |
| d e f |
in row-major form, it would be laid out in memory as:
+---+---+---+---+---+---+
| a | b | c | d | e | f |
+---+---+---+---+---+---+
and in column-major form, in would be laid out in memory as:
+---+---+---+---+---+---+
| a | d | b | e | c | f |
+---+---+---+---+---+---+
Remember that computer science is zero based, so where a mathematician would designate the first element in the first row as a_{11}, we will be using zero based indicies so we will designate it as a_{00}.
Most modern program languages use row-major form to store two dimensional arrays (or in this discussion matrices). So what you might ask? Well, because we are mapping a two dimensional array to a one dimensional array, and all we really know about the one dimensional array is its starting point in memory, we need to be able to change the pair (row, col) into a single index. You should convince yourself that the following equation is correct, assuming that nRow and nCol are the number of rows and columns in the matrix.
index = nCol * row + col
So, now write some code to add to matrices together. In pseudo-code form this would be:
A <-- read in first n-by-m matrix
B <-- read in second n-by-m matrix
C <-- initialize a n-by-m matrix to all zero elements.
for(r = 0; r < nRow; r++)
for(c = 0; c < nCol; c++)
C[r][c] = A[r][c] + B[r][c]
print C
It is an implementation detail to decide if you want to use fix sized matrices, i.e. 'A[2][2]', or potentially use a dynamically allocated matrix, i.e. 'A = malloc(nRow * nCol * sizeof(int));' (assuming we are storing integers). This will determine exactly how the addition line in the above pseudo-code would be written.
Hope this helps, and kinda show you how to approach problems like this.
Don't be afraid to ask additional questions if you get stuck on attempting the implementation.
Best of Luck,
T
I don't fully understand what your question is, but I can definately show you how to add two matricies of the same length elementwise, if that's what you're looking for.
#include <stdio>;
int main()
{
//this part is declaring the two arrays you want to add,
//and the array you want to store the result in.
int arrayA[3];
int arrayB[3];
int result[3];
//this part is just initializing the data in the array
arrayA[0] = 1;
arrayA[1] = 2;
arrayA[2] = 3;
arrayB[0] = 5;
arrayB[1] = 6;
arrayB[2] = 7;
//loops from 0 to 2, and adds the nth element of arrayA and
// arrayB to store in result
for(int n =0; n < 3; n++)
{
result[n] = arrayA[n] + arrayB[n];
}
//at this point, result is the addition of your arrays.
//You can print it, or whatever it is you wanted to do with it.
return 0;
}
There are many different things that could be 'adding matricies', but this is one of them.
However, the code you submitted looks like you're trying to store numbers from the keyboard into a 2D array. You're on the right track there, but on your first nested for loop your inner loop goes too far, so it's going outside of the array bounds. Try more liek this:
int matris[2][2];
for(int i=0;i<2;i++)
{
//you had j<4 here. That will put you in invalid memory!
for(int j=0;j<2;j++)
{
printf("Sayi giriniz: "); scanf("%d",&matris[i][j]);
}
}
//you had i<3 here. That will also put you in invalid memory.
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
printf("%d ",matris[i][j]);
}
printf("\n");
}
I hope I've addressed whatever question you were going for.
İyi şanslar!

c beginner, vectors

I'm a c beginner and i've a problem (as usual). I wrote this simple program:
#include <stdio.h>
#define SIZE 10
main()
{
int vettore[9];
int contatore1,contatore2;
for(contatore1 = 0; contatore1 <= 9; ++contatore1)
{
vettore[contatore1] = contatore1*2;
}
printf("%d\n\n", vettore[9]);
for(contatore2 = 0; contatore2 < 10; ++contatore2)
{
printf("%d\n", vettore[contatore2]);
}
printf("\n%d\n", vettore[9]);
return 0;
}
The output of this program is:
18
0
2
4
6
8
10
12
14
16
9
10
Why the value of vettore[9] changes 3 times? And why it has the correct value only on the first line of the output? thank you :)
C arrays are zero based so valid indexes for a 9 element array are [0..8]. You are writing beyond the end of your array. This has undefined results but is likely corrupting the next stack variable.
In more detail... vettore has 9 elements, which can be accessed using vettore[0] ... vettore[8]. The final iteration of your first loop writes to vettore[9]. This accesses memory beyond the end of your array. This results in undefined behaviour (i.e. the C standard does not specify expected outcome here) but it is likely that the address of vettore[9] is the same as the address of contatore2, meaning that the latter variable is written to.
You have a similar problem in the next loop which prints more elements than vettore contains.
You can fix this by changing your loops to
for(contatore1 = 0; contatore1 < 9; ++contatore1)
for(contatore2 = 0; contatore2 < 9; ++contatore2)
Note that it would be safer if you changed to calculating the size of the array instead, by using sizeof(vettore)/sizeof(vettore[0]) in the exit test of your loops in place of hard-coding 9.
Your array vettore has 9 elements, but by referencing vettore[9], you're actually referencing the 10th element (since element indexing starts from 0). So it's some random location on the stack, without a well-defined value.
The solution is to index only up to vettore[8], or define vettore to have size 10.
check this out:
for(contatore2 = 0; contatore2 < 10; ++contatore2)
{
printf("%d\n", vettore[contatore2]);
}
you are displaying 11 elements of the vettore array (which is defined as a 9 ints array). I think that the error is in the random allocation on the stack
the vettore size as you defined is 9
int vettore[9];
and in your loop you start from 0 till 9 so you are playing with 10 elements of the array and not 9 (size of the array)
you should define the array with size 10
int vettore[10];
Arrays (i.e. "vectors") start at index zero NOT one; it's contents may be, for example, 5 but it will occupy index locations of 0,1,2,3,4....
[1][2][3][4][5] <- Five items
0 1 2 3 4 <- Their respective locations in the array
Same goes for visualizing characters in strings.....(technically the location in memory contains ASCII value-- look into that for fun ;) )
['c']['a']['t'] <- Three items
0 1 2 <- Their index location in the array
I suggest Kochan's C Programming book; great for starting out!!!

Resources