going out of bounds in array of structs in C [duplicate] - c

This question already has answers here:
Array index out of bound behavior
(10 answers)
Closed 7 years ago.
Suppose I declare the following
typedef struct{
int age;
int weight;
} Man;
Then I make an array of Man such as
Man *manArr = malloc(sizeof(Man) * 2);
My understanding is that I now have two cells each capable of holding a Man type in them..but how am I able to do this then?
manArr[45] = (Man) {33, 23};
I would have imagined that I would have seg faulted because there only exists two cells but I can printf the values of manArr[45]. What's a good way to for example go through struct arrays, do something to their fields, and move on to the next without "going out of bounds" per say?
Thanks

Accessing out-of-bounds is not guaranteed to segfault. It is defined by the C standard as undefined behavior, i.e. anything can happen, including seemingly error-free behavior.
What's a good way to for example go through struct arrays, do something to their fields, and move on to the next without "going out of bounds" per say?
Remember the size of the array.
const size_t manArrSize = 2;
Man *manArr = malloc(sizeof(Man) * manArrSize);
for (size_t index = 0; index < manArrSize; ++index)
{
// Access `manArr[index]`.
}

Going out of bounds of an array causes undefined behaviour. This means that anything could happen. If you're lucky you'll get a segfault, but you may also get cases where the memory location happens to be somewhere you can access.
As for move on to the next without "going out of bounds":
You could either use an extra variable to store the size of the array, or decide on a sentinel value in the array (and allocate one more slot for it) so that if a certain element is equal to the sentinel value, you know it is the end. For example, argv uses NULL as the sentinel value.

Related

Why is the length of the array 3 when I have added 4 elements? [duplicate]

This question already has answers here:
Undefined, unspecified and implementation-defined behavior
(9 answers)
Accessing an array out of bounds gives no error, why?
(18 answers)
Closed 2 years ago.
#include <stdio.h>
#include <conio.h>
int main() {
int arr[] = {1,2,3};
arr[3] = 4;
printf("%d", sizeof(arr) / sizeof(1)); // To print the length of arr
getch();
return 0;
}
I first created this array of length 3 and then at index 3 I put 4 as its value. So the length should be 4 now, but still, after compiling it is printing 3. Why?
Arrays in C do not automatically extend themselves if you index outside the defined range. When you write
arr[3] = 4;
you are writing outside the bounds of the array.
The problem is that C does not require any kinds of bounds checking on array accesses and places no requirement on the compiler or runtime environment to handle out-of-bounds indexing in any particular way - the behavior is undefined. Any result is possible, including appearing to work as expected. You could also overwrite another variable. You could corrupt the stack frame leading to a crash later.
An array's size is fixed over its lifetime. You can allocate space dynamically with malloc or calloc and resize it using the realloc function, but again that doesn't happen automatically, you have to write the code to keep track of the current size and resize as necessary.
Why is the length of the array 3 ...
Because you defined it like that here
int arr[] = {1,2,3};
Using [] and three initialisers, size 3, not going to change.
... when I have added 4 elements?
You did not add 4 elements, you created it with initially three elements, they were not added.
You did not even add a single element later.
In this code
arr[3] = 4;
you wrote a value to a memory location just behind the array. The array is not changed by that, especially not its size. Doing this causes Undefined Behaviour by the way.
C is like that, it allows you to do all kind of unwise things, without kindly telling you.
You cannot create an array and then try to resize it. Arrays have a fixed size. If you want to store data dynamically, that is, with variable size, you need to use data structure.

(C) Why can I access array elements beyond the given limit? [duplicate]

This question already has answers here:
Accessing an array out of bounds gives no error, why?
(18 answers)
Closed 4 years ago.
So I've been learning C for more than about a year, and never in my studies have I ever thought this was possible:
#include <stdio.h>
#include <stdlib.h>
int main()
{
struct exterior
{
int x;
} *ptr;
ptr = (struct exterior *)malloc(sizeof(struct exterior[3]));
ptr[0].x = 1;
ptr[1].x = 2;
ptr[2].x = 3;
ptr[3].x = 4;
ptr[4].x = 5;
ptr[5].x = 6;
printf("%d %d %d %d %d %d", ptr[0].x, ptr[1].x, ptr[2].x, ptr[3].x, ptr[4].x, ptr[5].x);
return 0;
}
So at first I followed the rules of C; I allocated the memory required for 3 structure array elements to a structure pointer. I used to pointer to access the variable that was in the structure, while using an index to specify the structure array element.
For some reason, I then decided to try to access the array element beyond the given limit, even if I knew that the outcome would probably be the program crashing, but I did it anyways.
To my surprise, there was no crash.
Instead, the program worked. It printed out the value I had given to the variable with no problems. How is this possible?
Later on, I tried it with an int array. It worked as well! Am I doing something wrong?
When you create on array on C, the program allocates the memory you need for that and gives you the pointer for the first element. So when you say array[0], what you are doing is summing 0 to the base pointer of that array, therefore array[1] is increasing 1(4 bytes to be more precise) to the inicial pointer, so you can see the 2 element and so on (Dont forget that the array is a continous segment of memory, every value is next to his previous one). If you try to reach a position out of the array, the program will not crash, what it will do is read the memory from where it is pointing, which in most cases will most probably be garbish, but C has no problem with it, this language allows you to do pretty much everything!
Hope it helps :)

How does an uninitialized array affect the outcome? (no debugging)

Line 1:
int temp2 [4];
for(j=0;j<=4;j++){
for(i=0;i<=4;i++) {
temp2[j] = temp2[j] + election[i][j];
}
}
printf("%d",temp2[3]);
In this above example, the nested for loops sums up the columns of a 5x5 table.
However, the last column is always summed up incorrectly.
When I changed Line 1 to:
int temp2[4] = {0};
All of a sudden the calculations came out perfectly! What exactly happened between the initialization of the array?
If an array is uninitialized, does that mean its last element will always contain some garbage value?
If an array is uninitialized, does that mean its last element will always contain some garbage value?
Whether they contain a garbage value or any value at all is a matter of interpretation, because any attempt to read from such uninitialized variables is undefined behaviour (UB)1. So, you can't even check what is stored in those variables. In practice, UB may manifest itself as "garbage" values being printed out, but technically anything could happen.
Also note that you are accessing the array out of bounds. That is also UB.
for(j=0;j<=4;j++){ /* Oops! Should be j < 4 */
[1] This is a simplification. In practice, implementations can assign unspecified values to uninitialized variables, or use trap representations. This means the results or reading an uninitialized variables could simply be unspecified. But they could also do whatever a given implementation does when a trap value is read. I find it easier to lump everything under UB. See related question: What happens to a declared, uninitialized variable in C? Does it have a value?
Yes, an uninitialized array will contain unpredictable garbage. You must initialize it.
If an array is uninitialized, does that mean its last element will always contain some garbage value?
If the array is not global or static, yes it will contain the garbage value. The BSS initializes the static or globalvariable or memory location to default values unless the variable is initially assigned some value.
Thus, the information at the memory location is overwritten by compiler the program may crash.
Now, when you are accessing that memory what you get is undefined behavior.
Also, note that the snippet is accessing the array out of bounds. So, please use:
int temp2 [4];
for(j=0;j<=3;j++){
for(i=0;i<=3;i++) {
or
int temp2 [4];
for(j=0;j<4;j++){
for(i=0;i<4;i++) {
First, As Jonathan Leffler mentioned, You are looping too much - You initialized an array of 4 but looping 5 times. Try changing your outer loop to j<4 and inner loop to i<4:
Line 1: int temp2 [4];
for(j=0;j<4;j++){
for(i=0;i<4;i++) {
temp2[j] += election[i][j];
}
}
printf("%d",temp2[3]);
You should also initialize your array, as you can't predict what is in memory at the point of creation (also depends on what language you're using)
An uninitialized array will contain garbage data. I've notice that in the last version of visual studio if the array is of simple data types such as int than the compiler/ide automatically initialize it to zeros, but I wouldn't rely on it. As a rule, I recommend you initialize your arrays before you start doing operations like summing etc.

how to loop through array using pointer without known the size of the array [duplicate]

This question already has answers here:
Length of array in function argument
(9 answers)
Closed 8 years ago.
I have a question about loop through array using pointer, for example:
bool loopArray(int* array)
{
/*for(){}*/
}
within this function, I need to loop through this array without known the size of the array, how to loop it?
You can't.
Errrm, that's it.
You either provide a size parameter:
bool loopArray(int* array,size_t sz)
{
for(size_t i=0;i<sz;++i){
//Do stuff with array[i]....
}
}
Or a pointer to the 'end' of the array. You're allowed to point to one past the end and convention is to pass one-past-the-end as end. That allows you to specify 'empty' when begin==end:
bool loopArray(int* array,int* end)
{
for(;array!=end;++array){
//Do stuff with *array....
}
}
Looking at the previous example you would have defined int* end=array+sz before calling.
The second is faster and has the added benefit that other C programmers will start to recognize you as one of their own! If you see that as a benefit....
PS: For completeness: You can ensure you have a 'sentinel'. A sentinel is some value that indicates 'end'. The C standard library uses '\0' as the sentinel in character strings. Mores the pity.
That trick can work particularly when you're dealing with arrays of pointers and use NULL as the sentinel.
However it's not something to recommend as a general answer. It's error-prone, has a big overhead if you need to know the size, it restricts your ability to access 'sub-arrays' without modifying them and forbids you from using the sentinel as a value and breaks programs that do so by accident.
Other than that it's great.
it is impossible. You need some kind of information about the size; otherwise you will inevitabilly go past its borders...
A pointer doesn't "contain" any information about the size of the array that was allocated; it only points to a place in memory.
EXCEPT
There might be a way around; if you know what is the last element in your array (which MUST always be present then). This is used for example in char arrays (where the last element is \0)
You can't.
But you could do something on the lines of how the C standard library models strings. Given a char*, or a const char*, functions like strlen stop once 0 is reached (known as the null terminator).
So (i) either reserve an int value which acts as your terminator, or (ii) pass the length.
Either way, pass a const int* if you don't intend to modify the contents.

handling data violation in c

I am starting to learn c and cannot find a clear example of handling memory violations. Currently I have written a piece of code that uses a variable and an array.
I assign a value to the variable and then populate the array with a set of initial values. However one of the values in the array is being saved at the same address as the variable and hence overwriting the variable.
Could some one please give me a simple example of how to handle such errors or to avoid such errors....thanks
Once an error such as a memory violation has occurred in C, you cannot 'handle' it. So, you have to avoid it in the first place. The way to do what you want is as follows:
int a[10];
int i;
for( i = 0; i < 10; i++ )
a[i] = 5;
This is a guess but seems pretty much your problem.
You are overwriting beyond the bounds of the array.
C does not guard you against writing beyond the bounds of an allocated array. You as a programmer must ensure you do not do so. Failing to do so will result in Undefined Behavior and then anything can happen(literally) your program might work or might not or show unusual behavior.
For eg:
int arr[10];
Declares an array of 10 integers and the valid subscript range is from 0 to 9,
You should ensure your program uses valid subscripts.

Resources