why does this C code outputs 1 - c

Is there any reason why:
void function_foo(){
int k[8];
function_math(k, 8);
}
void function_math(int *k, int i){
printf("value: %d", k[i]);
}
The main execute function_foo();
The output will be 1? There's no initialization for elements of matrix k.
Maybe something with the length of int in memory?
I am new to C concepts, the pointers and everything.

It is undefined behaviour to evaluate k[8], since k only has 8 elements, not 9.
There is little point arguing about the consequences of undefined behaviour. Anything could happen. Your program is not well-formed.
(Note that it would even be undefined behaviour to evaluate k[0], ..., k[7], since they are unini­tia­lized. You have to write to them first, or initialize the array, such as int k[8] = { 1, 2 };.)

This is the value which is at the memory position after the last element of your declared array.
If you run this code in a week again, it could be 42 or anything else which is stored at this time on this specific memory address. Also a segmentation fault could be possible in this case.

You are stepping out of the bounds of the array k.
To access the last element of k try using function_math(k, 7)
The array is also not initialized so the values inside will be undefined.

Related

Accessing variable after an array by trying to access a position greater than its dimension in C [duplicate]

This question already has answers here:
How dangerous is it to access an array out of bounds?
(12 answers)
Accessing an array out of bounds gives no error, why?
(18 answers)
Closed 3 years ago.
Since in this example I'm able to read value of integer2 thanks to pointer arithmetic:
#include <stdio.h>
int main() {
int integer1 = 1;
int integer2 = 2;
int *p = &integer1;
p++;
printf("%d\n", *p);
}
with output:
$ ./test
2
I was wondering why in this example:
#include <stdio.h>
int main()
{
int array[2] = {0, 1};
int variable = 0;
for(int i = 0; i < 3; i++) {
printf("%d\n", array[i]);
}
}
then I'm not able to read the value of variable trying to point the next integer but that's what I get:
0
1
336859392
I tried printing the values of &array[0] &array[1] and &variable and this is what I got:
161695488
161695492
161695480
Not only the address of variable is less than the one of the first elements of the array, but it's not even the previous one.
Why in the first example variables address are contiguous and in the second one not?
There is probably something I don't understand on how variables and buffers are allocated in the stack.
EDIT:
I know this should not be done, but I'm trying to understand buffer overflows (more realistically the buffer should be of character, given as input by an user), and the goal should be to alter the value of the variable. So what I'm trying to understand is if it's possible to know exactly where the variable actually is in memory.
EDIT2:
Turns out that giving -fno-stack-protector makes it work as expected, so gcc is adding by default some sort of protection in order to avoid buffer overflows
The placement of local variables is a detail of the implementation. They may be placed in any order it deems appropriate.
Attempting to read past the bounds of an array invokes undefined behavior. The inconsistent results you see are a manifestation of that.
As an example, if I run your first code snippet, I do not get 2 as the output. When printing the addresses of each variable, I get:
&integer1=0x7ffcfa6e8c24, &integer2=0x7ffcfa6e8c20
So in my case the implementation puts integer1 after integer2.

code order with variable length array

In C99, is there a big different between these two?:
int main() {
int n , m;
scanf("%d %d", &n, &m);
int X[n][m];
X[n-1][m-1] = 5;
printf("%d", X[n-1][m-1]);
}
and:
int main(int argc, char *argv[]) {
int n , m;
int X[n][m];
scanf("%d %d", &n, &m);
X[n-1][m-1] = 5;
printf("%d", X[n-1][m-1]);
}
The first one seems to always work, whereas the second one appears to work for most inputs, but gives a segfault for the inputs 5 5 and 6 6 and returns a different value than 5 for the input 9 9. So do you need to make sure to get the values before declaring them with variable length arrays or is there something else going on here?
When the second one works, it's pure chance. The fact that it ever works proves that, thankfully, compilers can't yet make demons fly out of your nose.
Declaring a variable doesn't necessarily initialize it. int n, m; leaves both n and m with undefined values in this case, and attempting to access those values is undefined behavior. If the raw binary data in the memory those point to happen to be interpreted into a value larger than the values entered for n and m -- which is very, very far from guaranteed -- then your code will work; if not, it won't. Your compiler could also have made this segfault, or made it melt your CPU; it's undefined behavior, so anything can happen.
For example, let's say that the area of memory that the compiler dedicates to n happened to contain the number 10589231, and m got 14. If you then entered an n of 12 and an m of 6, you're golden -- the array happens to be big enough. On the other hand, if n got 4 and m got 2, then your code will look past the end of the array, and you'll get undefined behavior -- which might not even break, since it's entirely possible that the bits stored in four-byte segments after the end of the array are both accessible to your program and valid integers according to your compiler/the C standard. In addition, it's possible for n and m to end up with negative values, which leads to... weird stuff. Probably.
Of course, this is all fluff and speculation depending on the compiler, OS, time of day, and phase of the moon,1 and you can't rely on any numbers happening to be initialized to the right ones.
With the first one, on the other hand, you're assigning the values through scanf, so (assuming it doesn't error) (and the entered numbers aren't negative) (or zero) you're going to have valid indices, because the array is guaranteed to be big enough because the variables are initialized properly.
Just to be clear, even though variables are required to be zero-initialized under some circumstances doesn't mean you should rely on that behavior. You should always explicitly give variables a default value, or initialize them as soon as possible after their declaration (in the case of using something like scanf). This makes your code clearer, and prevents people from wondering if you're relying on this type of UB.
1: Source: Ryan Bemrose, in chat
int X[n][m]; means to declare an array whose dimensions are the values that n and m currently have. C code doesn't look into the future; statements and declarations are executed in the order they are encountered.
In your second code you did not give n or m values, so this is undefined behaviour which means that anything may happen.
Here is another example of sequential execution:
int x = 5;
printf("%d\n", x);
x = 7;
This will print 5, not 7.
The second one should produce bugs because n and m are initialized with pretty much random values if they're local variables. If they're global, they'll be with value 0.

Does array[-1] give the last element in the array?

programming my arduino microcontroller board in C, I noticed a strange behaviour.
Because of an logic mistake in my program the controller accessed the -1th element of an integer array.
int array[5];
array[4] = 27;
// array[-1] gives 27 now.
Is it correct that I get the last element of an array by using -1 as the element selector?
No, accessing elements outside of the index range is undefined behavior. In your case, the element at the address just prior to the beginning of your array is set to 27.
Since accessing array elements in C is nothing more than doing "straight" pointer arithmetic, passing negative indexes is not disallowed. You could construct a legitimate use case where indexes are negative and positive:
int raw[21], *data = &raw[10];
for (int i = -10 ; i <= 10 ; i++) {
data[i] = i;
}
No; array[-1] will not access the last element. It's more likely that the memory location just before the array has 27 stored in it. Try this:
array[4] = 27;
array[-1] = 0;
Then test whether array[-1] == array[4]. They will not be equal (assuming your program doesn't crash when assigning to array[-1]).
Accessing arrays with index out of bounds does not always crash your program. If the memory accessed by -1 is under your program control than an undefined value will pop out (which was stored by some other data created by your program). In your case it is mere coincidence.
No, that is incorrect according to the Standard. Accessing an element outside the array invokes Undefined Behaviour.
Your implementation might (I doubt it!) provide that functionality; but you really should not rely on it.
Try this:
#include<stdio.h>
int main()
{
int raw[4], *data = &raw[2];
raw[0]=0;
raw[1]=1; // -1 index for data
raw[2]=2;
raw[3]=3;
for (int i = 0 ; i < 2 ; i++) {
printf("\nvalue =%d i=%d\n",data[i],i);
}
printf("\nIndex,[-1]=%d\n", data[-1]);
return 0;
}
EDIT: Conclusion is that -1 will access last memory location.
If you are referring to C (and you are), then no. If you try to access an array with a negative index, you will get an out of bounds exception. However, Lua implements this exact thing as a feature. If you access a Lua array with an index of -1, it will read the last element of the array. An index of -2 will read the second-to-last element, and so-on.
Side note: you can annoy your coworkers by writing this
foo = {1,2,3,4,5,6,7,8,9,0}
print(foo.length() * -1])
This prints 1. Annoying, isn't it.

Array Allocation causing terminal to hang

I came across this code accidentally:
#include<stdio.h>
int main()
{
int i;
int array[3];
for(i=0;i<=3;i++)
array[i]=0;
return 0;
}
On running this code my terminal gets hanged - the code is not terminating.
When I replace 3 by 2 code runs successfully and terminates without a problem.
In C there is no bound checking on arrays, so what's the problem with the above code that is causing it to not terminate?
Platform - Ubuntu 10.04
Compiler - gcc
Just because there's no bound checking doesn't mean that there are no consequences to writing out of bounds. Doing so invokes Undefined Behavior, so there's no telling what may happen.
This time, on this compiler, on this architecture, it happens that when you write to array[3], you actually set i to zero, because i was positioned right after array on the stack.
Your code is reading beyond the bound of array and causing an Undefined Behavior.
When you declare an array of size 3. The valid index range is from 0 to 2.
While your loop runs from 0 to 3.
If you access anything beyond the valid range of an array then it is Undefined Behavior and your program may hang or crash or show any behavior. The c standard does not mandate any specific behavior in such cases.
When you say C does not do bounds checking it actually means that it is programmers responsibility to ensure that their programs do not access beyond the beyonds of the allocated array and failing to do so results in all safe bets being off and any behavior.
int array[3];
This declares an array of 3 ints, having indices 0, 1, and 2.
for(i=0;i<=3;i++)
array[i]=0;
This writes four ints into the array, at indices 0, 1, 2, and 3. That's a problem.
Nobody here can tell exactly what you're seeing -- you haven't even specified what platform you're working on. All we can say is that the code is broken, and that leads to whatever result you're seeing. One possibility is that i is stored right after array, so you end up setting i back to 0 when you do array[3]=0;. But that's just a guess.
The highest valid index for array is 2. Writing past that index invokes undefined behaviour.
What you're seeing is a manifestation of the undefined behaviour.
Contrast this with the following two snippets, both of which are correct:
/* 1 */
int array[3];
for(i=0;i<3;i++) { array[i] = 0; }
/* 2 */
int array[4];
for(i=0;i<4;i++) { array[i] = 0; }
You declared array of size 3 which means (0,1,2 are the valid indexes)
if you try to set 0 to some memory location which is not for us unexpected (generally called UB undefined behavior) things can happen
The elements in an array are numbered 0 to (n-1). Your array has 3 spots, but is initializing 4 location (0, 1, 2, 3). Typically, you'd have you for loop say i < 3 so that your numbers match, but you don't go over the upper bound of the array.

How is this loop ending and are the results deterministic?

I found some code and I am baffled as to how the loop exits, and how it works. Does the program produce a deterministic output?
The reason I am baffled is:
1. `someArray` is of size 2, but clearly, the loop goes till size 3,
2. The value is deterministic and it always exits `someNumber` reaches 4
Can someone please explain how this is happening?
The code was not printing correctly when I put angle brackets <> around include's library names.
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
int main() {
int someNumber = 97;
int someArray[2] = {0,1};
int findTheValue;
for (findTheValue=0; (someNumber -= someArray[findTheValue]) >0; findTheValue++) {
}
printf("The crazy value is %d", findTheValue);
return EXIT_SUCCESS;
}
Accessing an array element beyond its bounds is undefined behavior. That is, the program is allowed to do anything it pleases, reply 42, eat your hard disk or spend all your money. Said in other words what is happening in such cases is entirely platform dependent. It may look "deterministic" but this is just because you are lucky, and also probably because you are only reading from that place and not writing to it.
This kind of code is just bad. Don't do that.
Depending on your compiler, someArray[2] is a pointer to findTheValue!
Because these variables are declared one-after-another, it's entirely possible that they would be positioned consecutively in memory (I believe on the stack). C doesn't really do any memory management or errorchecking, so someArray[2] just means the memory at someArray[0] + 2 * sizeof(int).
So when findTheValue is 0, we subtract, then when findTheValue is 1, we subtract 1. When findTheValue is 2, we subtract someNumber (which is now 94) and exit.
This behavior is by no means guaranteed. Don't rely on it!
EDIT: It is probably more likely that someArray[2] just points to garbage (unspecified) values in your RAM. These values are likely more than 93 and will cause the loop to exit.
EDIT2: Or maybe someArray[2] and someArray[3] are large negative numbers, and subtracting both causes someNumber to roll over to negative.
The loop exits because (someNumber -= someArray[findTheValue]) doesnt set.
Adding a debug line, you can see
value 0 number 97 array 0
value 1 number 96 array 1
value 2 number 1208148276 array -1208148180
that is printing out findTheValue, someNumber, someArray[findTheValue]
Its not the answer I would have expected at first glance.
Checking addresses:
printf("&someNumber = %p\n", &someNumber);
printf("&someArray[0] = %p\n", &someArray[0]);
printf("&someArray[1] = %p\n", &someArray[1]);
printf("&findTheValue = %p\n", &findTheValue);
gave this output:
&someNumber = 0xbfc78e5c
&someArray[0] = 0xbfc78e50
&someArray[1] = 0xbfc78e54
&findTheValue = 0xbfc78e58
It seems that for some reason the compiler puts the array in the beginning of the stack area, then the variables that are declared below and then those that are above in the order they are declared. So someArray[3] effectively points at someNumber.
I really do not know the reason, but I tried gcc on Ubuntu 32 bit and Visual Studio with and without optimisation and the results were always similar.

Resources