Strange array errors C - c

This may be due to my lack of understanding of C, but I'm getting some (what i would call) obscure errors when dealing with arrays:
Here is the code:
int * generateRandomArray(int numPageReplacements) {
// Seed random number generator
srand(time(NULL));
int * randPages = (int *)malloc(sizeof(int)*numPageReplacements);
for (int i = 0; i < numPageReplacements; i++) {
randPages[i] = rand() % 10; // generate (with uniform distribution) number 0 - 9
printf("%d ", randPages[i]); // for testing purposes
}
printf("\nRandomPages[3] = %d \n" ,randPages[3]);
return randPages; // return array pointer
}
Output:
7 9 4 6 4 6 5 7 6 3
RandomPages[3] = 6
Program ended with exit code: 0
If I run this back to back (take random numbers generated above) it will give 4 sometimes (what one would expect) and 6 at others (it's like it doesn't know the bounds of each array cell).
When I attempt to obtain the array from this function from the call:
int * ary = generateRandomArray(int numPageReplacements);
printf("Size of ary = %lu",sizeof(ary));
Output:
Size of ary = 8
It's equal to 8 no matter WHAT numPageReplacements is.
Compiler:
Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.0.0
Thread model: posix
Am I missing something here?

Calling sizeof on an pointer give you only the size of that pointer, which is what ary is. An array would be int ary[10];
You are working with dynamically allocated memory, not arrays. Sure, they work like arrays, kind of, because you can use [] to access its elements, but under the hood, they are very different beasts.
Just so you know, there is no way to find out how big an an array, or even if it is an array at all, as opposed to just the address of a single int, that's being passed to a function. A pointer merely stores a memory address. Interpreting what's at that address is up to the programmer. That's why C functions that accept arrays/buffers always take the size of that array/buffer as a separate parameter.

sizeof(ary), ary is an integer pointer and its size is 8 bytes(64bit) in a 64 bit machine that you are running.

Related

C - how are dynamic arrays printed?

I'm a bit baffled with whether I'm printing my dynamic array correctly. I'm parsing an input file. Say the input file is:
x 6 9 15,
then my goal is to store 1, 2 and 3 into an array called x. It's doing exactly this. I've set the size of the array using:
arr = malloc(sizeof(int)*noValues);
(I also have int *arr declared as a global variable in my file)
where noValues is equal to the number of values encountered in the input file (in this case 3).
I then print the array using:
for (i = 0; i < noValues; i++) {
printf("arr[%d]: %d\n", j, arr[j]);
}
and get the following output:
arr[0]: 6
arr[1]: 9
arr[2]: 15
However, when I change the "noValues" in the for loop to 10, I get the following:
and get the output:
arr[0]: 6
arr[1]: 9
arr[2]: 15
arr[3]: 0
arr[4]: 0
arr[5]: 0
arr[6]: 49
arr[7]: 0
arr[8]: 17060496
arr[9]: 0
Why am I getting some non 0 values? Shouldn't they all be 0? Any clear-up would be appreciated. Is this normal C behaviour?
You are accessing "elements" out of the boundary of arr, this is undefined-behavior; that's why you get values that are seemingly random (but the application could just as well crash).
You're accessing past the end of the array, which is undefined behavior. Technically anything can happen when you do that, but there are two things that typically happen in practice: either the program will crash, or you'll just get the value of whatever bytes are located in memory past the end of the array. (But this isn't something that you can, or should, rely on.)
The uninitialized array behavior is not fix. The value of uninitialized array is zero ,garbage possible. if you want to get value zero of all the elements in the array then use bzero or memset function.

What happens if i don't use zero-based array in C

Can someone explain what would happen? Is it really necessary to start at index 0 instead of 1 (which would be easier for me)?
You can do whatever you want, as long as your array subscript is strictly less than the size of the array.
Example:
int a[100];
a[1] = 2; // fine, 1 < 100
What happens if I don't use zero-based array in C
Well, you can't. C arrays are zero based, by definition, by standard.
Is it really necessary to start at 0?
Well, this is no rule to prevent you from leaving index 0 unused, but then, you'll almost certainly not get the desired result.
Using non-zero based arrays in C is possible, but not recommended. Here is how you would allocate a 1-based array of 100 integers:
int * a = ((int*)malloc(100*sizeof(int)))-1;
The -1 moves the start of the pointer back one from the start of the array, making the first valid index 1. So this array will have valid indices from 1 to 100 inclusive.
a[1] = 10; /* Fine */
a[100] = 7; /* Also fine */
a[0] = 5; /* Error */
The reason why this isn't recommended is that everything else in C assumes that pointers to blocks of memory point to the first element of interest, not one before that. For example, the array above won't work with memcpy unless you add 1 to the pointer when passing it in every time.

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!!!

Array size less than the no. of elements stored in it

Is it possible to declare an array of size 1 and be able to store 5 elements in it and then retrieve them?
I try one such code where I declared an array arr[1] and then stored 5 elements into it. It was actually possible to store 5 elements! How was it?
If this is C (or C++), you can quite easily store more elements than the array is sized for:
#include <stdio.h>
int main (void) {
int x = 0;
int a[1]; // so that a[0] is the only valid element
a[1] = 7; // write beyond end of array
printf ("x=%d, &a[0]=%p, &a[1]=%p, &x=%p\n", x, &(a[0]), &(a[1]), &x);
return 1;
}
Doing so, however, leads to undefined behaviour, probably overwriting some other piece of information, and is not really a good idea.
On my system, that code above prints:
x=7, &a[0]=0xbf9bb638, &a[1]=0xbf9bb63c, &x=0xbf9bb63c
despite the fact I set x to zero and never explicitly changed it. That's because writing beyond the end of the array has affected it (as you can see from the two identical addresses for a[1] and x).

Assigning a value to a variable gets stored in the wrong spot?

I'm relatively new to C, and this is baffling me right now. It's part of a much larger program, but I've written this little program to depict the problem I'm having.
#include <stdio.h>
int main()
{
signed int tcodes[3][1];
tcodes[0][0] = 0;
tcodes[0][1] = 1000;
tcodes[1][0] = 1000;
tcodes[1][1] = 0;
tcodes[2][0] = 0;
tcodes[2][1] = 1000;
tcodes[3][0] = 1000;
tcodes[3][1] = 0;
int x, y, c;
for(c = 0; c <= 3; c++)
{
printf("%d %d %d\r\n", c, tcodes[c][0], tcodes[c][1]);
x = 20;
y = 30;
}
}
I'd expect this program to output:
0 0 1000
1 1000 0
2 0 1000
3 1000 0
But instead, I get:
0 0 1000
1 1000 0
2 0 20
3 20 30
It does this for any number assigned to x and y. For some reason x and y are overriding parts of the array in memory.
Can someone explain what's going on?
Thanks!
tcodes[3][0] = 1000;
tcodes[3][1] = 0;
are writing off the end of your array twice. [3] allocates slot ids 0-2 and [1] only allocates 1 actual slot [0].
Change your initialization of tcodes to signed int tcodes[4][2]; for 4 entries by 2 entries.
The other answers are right, but to help explain what's actually happening:
You have the following local declarations:
signed int tcodes[3][1];
int x, y, c;
Those get stored right next to each other in the stack frame in memory:
tcodes
x
y
z
tcodes has 3 spots, and trying to write to tcodes[n] just means to find where tcodes points to in memory and move over to the nth spot (I'm going to ignore your second dimension since it was just 1 anyway). If you try to write to spot 3, it's going to move over 3 spots from the beginning of tcodes, even though tcodes isn't that big. Since x is located right after tcodes, in the spot tcodes[3] would be in, that memory gets overwritten and the value of x changes. tcodes[4] would overwrite y, and tcodes[5] would overwrite z. If you kept making n bigger (or negative, which is legal), you could overwrite anything you're allowed to access in memory, which can screw up your program in bad and hard-to-find ways
Change it to this:
signed int tcodes[4][2];
If You define an array like this:
int somearr[3];
You get an array that has 3 elements. Indexes start form 0, so those elements are:
somearr[0]
somearr[1]
somearr[2]
Arrays and other variables defined inside a function, like in Your code, are allocated on the stack. It just so happens, that variables x and y are placed on the stack next to Your array. If you try to access elements
tcodes[3][0] or tcodes[3][1]
You access a part of a stack, that is behind Your array and, as Your output show, it's the spot, where variables x and y are placed.
In fact definition like this
signed int tcodes[3][1];
creates an array containing 3 elements, each of which is an array too - an array containing one signed int. When You write tcodes[1][1], You are accessing non-existing "second" element of your second array. The place in memory, that the compiler accesses when it interprets tcodes[1][1] overlaps with tcodes[2][0];
As you are writing beyond the array boundaries, you are writing on the memory allocated to x and y variables on stack. In this case, they happen to be same as tcodes[3][0] == x and tcodes[3][1] == y as the addresses are same.
If you are doing it in a called function and the array is passed by reference, you might end up in stack corruption.
The bottom line is that in C, arrays are 0 based.
You need to pay attention to the solution given by Robin Oster above. The other folks may be giving you "too much information". Just count the number of items in each dimension better, don't forget the zero'th item counts!

Resources