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

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 :)

Related

Can someone help me with problem with sorting data structures in C-language [duplicate]

This question already has answers here:
How do I check if a value matches a string
(4 answers)
How do I properly compare strings in C?
(10 answers)
Closed 4 years ago.
So I've been new in structures so i tried to sort it like normal bubble sort but it won't work and also ti gives me error like "assignment with expression to array type"
I just want to sort names of cocktails in reverse way form 'z' to 'a'.
I did rest of the code which works and i got stucked on this sort
I really tried every way I could think of so if someone can help me it would be great.
Thanks :)
typedef struct {
char name[20+1];
char sast1[20+1];
char sast2[20+1];
char sast3[20+1];
} kokteli;
j=i;
int s;
int flag;
char *pom;
while(1) {
flag = 0;
for(s=0; s<j; s++) {
if(k[s].name> k[s+1].name) {
pom = k[s].name;
k[s].name= k[s+1].name;
k[s+1].name= pom;
flag = 1;
}
} if(flag == 0){
break;
}
}
So I've been new in structures so i tried to sort it like normal
bubble sort but it won't work and also ti gives me error like
"assignment with expression to array type"
I won't speak to what your code is actually trying to achieve but I will address the error you are getting. The compiler should be pointing out these two lines:
k[s].name= k[s+1].name;
k[s+1].name= pom;
So for clarity sake let's point out the fact that k is an array of kokteli structs and those structs contain members that are arrays (name, sast1, etc). k[s].name and k[s+1].name are both an array of char which in C is not assignable. You can modify the elements (char) of the array via pointers to the memory address for each char in the array. You would do that like this:
k[s].name[n] = //where n is an integer from 0 to 20, assign value of nth element here)
Let's break this statement down:
k is a pointer to an array of kokteli structs
k[s] is actually a pointer to the address of the kokteli struct located at the memory address offset from k by s (the exact same thing in C as (k+s))
k[s].name is actually a pointer to the address of the member name of the kokteli struct located at offset s (can also be written in C as (k+s)->name or &k[s] //since the first member is name)
k[s].name[0] is the contents of the 0th element of the member name of the kokteli struct located at the memory address offset from k by s (can also be written in C as *(k+s)->name)
This is why the compiler doesn't complain about this line:
pom = k[s].name;
Now the caveat here is that the name of an array in C actually refers to a memory address for the beginning of the contents of that array. This means that it is a pointer itself. So since pom and k[s].name are actually both char *, pom now points to what k[s].name is pointing at.
Your if clause here:
if(k[s].name > k[s+1].name){
...
}
Is actually comparing memory addresses as k[s].name and k[s+1].name both point to the first element in the array. The difference is that one is located at a memory offset that is sizeof(kokteli) greater than the other (that is k[s+1].name) so this statement will never be true. I've made some code for you here that will nail this home.
As other people in the comments have pointed out, you will actually want to use strcmp (need to #include <string.h>) to compare the elements of the two arrays of type char. Reference for strcmp is located here.
So your if clause should look something like this
if(strcmp(k[s].name, k[s+1].name) > 0){
//k[s].name comes after k[s+1].name alphabetically
}
For more on how strcmp works, see this answer.

Dynamically declaring structs not working as expected [duplicate]

This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 5 years ago.
I'm having issues with my program, and I'm trying to break it down and I'm seeing that I'm having issues with memory allocation at a minimum.
I have a struct:
typedef struct{
int originX;
int originY;
char ticBoard[3][3];
int result;
int turn;
} simBoard;
I would expect the size of this struct (one single instance of it) to be (4 ints * 4 bytes) + (1 bye char * 3 * 3) or 25 bytes. When I run the sizeof() function on simBoard, I get a value of 28 bytes. I'm assuming that it's the 25 + 3 extra that I don't need to worry about.
The main issue is when I try to declare an array of this struct
simBoard* boardArray = (simBoard*)malloc(sizeof(simBoard)*size));
Assume size is some constant for this scenario. To my knowledge this should create an array of the simBoard struct, of size size. I should be able to go
boardArray[3]
And get the 4th item of boardArray correct? However I'm running into an issue with the memory allocation. When I run:
printf("%zu is the size of the array\n", sizeof(boardArray));
The return value is 8. I even tried to further sort out the issue:
simBoard* boardArray = (simBoard*)malloc(224);
When I ran the printf again, I'm still getting a value of 8 bytes for boardArray. If you guys could lead me in the right direction that'd be fantastic, as I'm absolutely stumped here.
Thank you!
You can indeed index the 4th struct in the array using the notation boardArray[3].
Bear in mind though that boardArray itself is a pointer type. That explains your printf output. Arrays with dynamic storage duration and pointer types are inextricably linked in C. For the avoidance of doubt, sizeof(boardArray) is sizeof(simBoard*).
C doesn't provide functionality to obtain the length of an dynamic array. You need to remember the length yourself.
Don't forget to call free(boardArray) when your done. The C runtime library will take appropriate measures to ensure that all the struct elements are freed.

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

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.

C global unsized array?

We had a school project, any information system using C. To keep a dynamic-sized list of student records, I went for a linked list data structure. This morning my friend let me see his system. I was surprised with his list of records:
#include <stdio.h>
/* and the rest of the includes */
/* global unsized array */
int array[];
int main()
{
int n;
for (n=0; n < 5; n ++) {
array[n] = n;
}
for (n=0; n < 5; n ++) {
printf("array[%d] = %d\n", n, array[n]);
}
return 0;
}
As with the code, he declared an unsized array that is global (in the bss segment) to the whole program. He was able to add new entries to the array by overwriting subsequent blocks of memory with a value other than zero so that he can traverse the array thusly:
for (n=0; array[n]; n++) {
/* do something */
}
He used (I also tested it with) Turbo C v1. I tried it in linux and it also works.
As I never encountered this technique before, I am presuming there is a problem with it. So, yeah, I wanna know why this is a bad idea and why prefer this over a linked list.
int array[];
Is technically known as an array with incomplete type. Simply put it is equivalent to:
int array[1];
This is not good simply because:
It produces an Undefined behavior. The primary use of array with incomplete type is in Struct Hack. Note that incomplete array types where standardized in C99 and they are illegal before.
This is Undefined behaviour. You are writing to unallocated memory (beyond the array). In order to compile this, the compiler is allocating at least one element, and you're then writing beyond that. Try a much bigger range of numbers. For example, if I run your code on Linux it works, but if I change the loop to 50,000, it crashes.
EDIT The code may work for small values of n but for larger values it will fail. To demonstrate this I've written your code and tested it for n = 1000.
Here is the link for CODEPAD, and you can see that for n = 1000, a segmentation fault happens.
Whereas with the same code with the same compiler, it is working for n = 10, see this link CODEPAD. So this is called Undefined behavior.
If you use linked lists you can check whether the memory is allocated properly or not.
int *ptr;
ptr = (int *)malloc(sizeof(int))
if(ptr==NULL)
{
printf("No Memory!!!");
}
But with your code the program simply crashes if tested with an array having a large bound.

Having trouble finding the length of an array in C? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
c dynamic memory allocation and sizeof()
I am trying to find the cache block by keeping a huge block of 16 MiB and by trying to access different elements each time to find the time. I just can't write the length of the array.
How can I write a for loop to iterate over the array. I need the length of the array; how can I find that? I have tried sizeof(a)/sizeof(a[0]) but this doesn't work or I am doing something wrong because my assignment sheet tells me it can hold 4 million int's..
register *a;
a = malloc(16777216);
int i;
for (i = 0; i < sizeof(a)/sizeof(a[0]); i = i + 1) {
printf("\ni = %d", i);
}
This only prints i = 0 i = 1.
The code sizeof(a) simply returns the size of the pointer register *a, and is completely unrelated to the size of the array that a points to.
C arrays do not track how many items they contain. You can use this syntax only if the size of the array is known at compile time. But you can't do it with an array allocated this way.
For this task, you'll need to track this information yourself. You can store that value in a variable, or you could append an array element with a special value that indicates it's the end of the array (much like we do with C strings).
a is a register pointer an not an array. so sizeof(a) will not return 16MB as you are expecting. please use 16777216 directly instead of sizeof()

Resources