I was having a little fun with C Programming and array pointers.
Can someone explain what is happening when I advance an array pointer beyond the size of the array?
It looks like I'm accessing the memory cell that is directly after the array, but I just want to be sure.
So many questions!
int arr[] = { 1, 2, 3, 4, 5 };
int *xPtr = arr;
for(int i = 0; i < 10; i++) {
printf("current pointer is %d\n", *xPtr++);
}
Results in:
current pointer is 1
current pointer is 2
current pointer is 3
current pointer is 4
current pointer is 5
current pointer is 0
current pointer is 127926431
current pointer is -759946469
current pointer is -492049712
current pointer is 32766
This was the only way I found to properly iterate through the array. Is this correct?
int arraySize = sizeof(arr) / sizeof(int);
for(int i = 0; i < arraySize; i++) {
printf("current pointer is %d\n", *xPtr++);
}
Results in:
current pointer is 1
current pointer is 2
current pointer is 3
current pointer is 4
current pointer is 5
You are accessing memory outside the array. Array has just 5 elements, and you increase the pointer beyond that, and dereference it. There are actually two kinds of bad things here: you are dereferencing outside the array, but you are also increasing the pointer more than one step beyond end of the array. Neither is allowed.
This is undefined behaviour, so anything could happen. In this case it looks like you are simply getting the memory contents after the array, interpreted as ints. In the context of your C program, they're just garbage values, because once you have undefined behaviour in C, all bets are off, the program could have crashed or worse.
If you want to make sense of a program which has UB, you gotta compile it, then look at the assembly code of that particular compilation. Just note that next time you compile it, result could be different (compiler switches, compiler or library updates, different computer...), and the new assembly code could have totally different behaviour (because the C code had UB). Generally this is not useful, UB is UB and it rarely makes sense to try and reason about what it does.
C has no array bounds checking, so C compiler does not perform any checks. In a modern PC operating system with memory protection, the OS will kill the program if you try to access memory that is not given to it, but it has coarse resolution (for example 4 KB pages), and there might be a lot of memory belonging to your program anyway, so OS might not notice anything bad for megabytes after the array.
2nd version looks good. Just remember that sizeof
works like that only for actual arrays, not for pointers, and not for array parameters of functions (because those are actually pointers, not arrays, despite the syntax).
You need to understand pointer increment *xPtr++
works by incrementing the size of the object it is pointing to. In your case being an int
, every operation does an increment of the sizeof(int)
depending on the size of int
in your system.
Since your array has only 5 elements, on a machine with a 4 byte int
, you cannot increment it more than 5 counts. Beyond that you are accessing memory that is not allocated for the array and accessing the value from those locations invokes undefined behavior.
Your second approach seems right, with a simple fix use the return type of sizeof()
from int
to size_t
although an implicit conversion happens on assignment
size_t arraySize = sizeof(arr) / sizeof(int);
for(size_t i = 0; i < arraySize; i++) {
printf("current pointer %p and value is %d\n", (void*)xPtr, *xPtr++);
}
C does not check for Array Bounds. So even if you access an array beyond it's size which is declared, it will not give any error. The answers to your questions, according to me :
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With