What happens if i don't use zero-based array in C - 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.

Related

Last element of a struct array - C

I'm a bit confused about a thing :
If I have an array of structs: table whith a length of X and I want to access the last element of it: table[X] or table[X-1]. If it's table[X-1], what table[X] contains ?
The indexing of array in C starts with zero, i.e. the first element will be in table[0], the second in table[1], the third in table[2] ... and the last on in table[X-1].
table[X] is outside of the arrays bounds. C does not have bounds checking, so compiler allows accessing it, but this is an undefined behaviour, i.e. you will never know what happens. Reading it can give back memory garbage or can lead to an OS exception like segmentation fault.
The answer is the same for any kind of array. If you have one with the size
X :
int a[5];
struct my_struct ms[10];
...
you specify the amount of elements in that array. Because the 1st element is element 0, the last element is always X - 1.
If you try to access the element a[X] you will get undefined behavior.
Structs work in memory the same way that an integer or some other basic data type would in this instances. Your array would just be separated by sizeof(struct) instead of sizeof(the basic data type).
It'd still start at 0, and end at X - 1. The type of arrays usually just really defined 2 things:
The amount of bytes per index, and how to treat the data.
Picture an array of size 3 with structs that contain 5 bytes of data. Your array would just be set as follows:
-----|-----|-----|????|
s1 |s2 |s3 |????|
Just because it exists, doesn't mean our program knows what it is. the 4th [3] index (????) would be an index out of bounds of our array. It is possible however you could get some meaningful value here, but very unlikely. Most of the time it will either be garbage, or cause an error.
Arrays in C use zero indexing, meaning they start with 0 and end with n-1. Not to be confused with array declarations, where you write the size expressed in number of items. The syntax for accessing an array and declaring one looks similar, which is why this can be confusing for beginners.
Example:
int main (void)
{
int array[5]; // allocate an array with 5 elements
array[0] = 0; // access first element
array[4] = 0; // access last element (index 4)
array[5] = 0; // BAD, accessing the array out of bounds: index 5 gives item number 6
}
And this is why the canonical way to write for loops in C is this:
for(int i=0; i<n; i++)
where n is the size of the array, and the iterator i will have the values from 0 to n-1.

Printing an empty 2d Array in C

I am writing a program that takes a 2D array and by use of a switch case, you can direct it to fill with random numbers and/or print the array among other things.
Before I fill the array with random numbers, I go to print the array just to see what it would do and I get this:
176185448 1 1 01430232144
32767180624652332767143023216832767
143023216832767 0 11430232192
32767176185344 1 0 14
143023220832767 0 0 0
0 0 0 0 0
This is my code for the print array function and I am passing plist from main:
void PrintArray2D(int plist[M][N])
{
size_t row, column; //counter
for (row = 0; row < M; ++row)
{
for (column = 0; column < N; ++column)
{
printf ("%5d" , plist[row][column]);
}
printf ("\n");
}
}
My Program is working fine otherwise. When I fill with random numbers and then print, my output is correct. The array size is 6 by 5. I'm just curious as to why, anything is being printed at all when it is supposed to be an empty array. And even more curious as to the specific output I am getting.
You are printing the value of uninitialized array. In this case the behavior of program is undefined. You may get any thing, either expected or unexpected result.
The value you are getting may be the some previous value stored at that location (called garbage value). Your program may gives erroneous result.
Are you initialising the array?
If not, you are more than likely getting the remains of whatever was in memory beforehand.
To initialise it to all zeros quickly, wherever it is defined have something like
int list[M][N] = {0};
Just a warning, the zero does not mean set all values to 0. It sets the first elements to the contents of the curly braces. So:
int values[M] = {1,2,3};
Would set the first three numbers to 1,2, and 3 and the remainder to zeros.
Variables in C must be initialized. If you don't initialize a variable (like an array) it contains some non-logic numbers (like address of a memory unit - the value which had been there before in that location of the memory)
The thing you're printing is that! you can't do this in some languages like Java, if you do so, you get an compilation error.
I hope this helps

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

changing the index of array

so far, i m working on the array with 0th location but m in need to change it from 0 to 1 such that if earlier it started for 0 to n-1 then now it should start form 1 to n. is there any way out to resolve this problem?
C arrays are zero-based and always will be. I strongly suggest sticking with that convention. If you really need to treat the first element as having index 1 instead of 0, you can wrap accesses to that array in a function that does the translation for you.
Why do you need to do this? What problem are you trying to solve?
Array indexing starts at zero in C; you cannot change that.
If you've specific requirements/design scenarios that makes sense to start indexes at one, declare the array to be of length n + 1, and just don't use the zeroth position.
Subtract 1 from the index every time you access the array to achieve "fake 1-based" indexing.
If you want to change the numbering while the program is running, you're asking for something more than just a regular array. If things only ever shift by one position, then allocate (n+1) slots and use a pointer into the array.
enum { array_size = 1000 };
int padded_array[ array_size + 1 ];
int *shiftable_array = padded_array; /* define pointer */
shiftable_array[3] = 5; /* pointer can be used as array */
some_function( shiftable_array );
/* now we want to renumber so element 1 is the new element 0 */
++ shiftable_array; /* accomplished by altering the pointer */
some_function( shiftable_array ); /* function uses new numbering */
If the shift-by-one operation is repeated indefinitely, you might need to implement a circular buffer.
You can't.
Well in fact you can, but you have to tweak a bit. Define an array, and then use a pointer to before the first element. Then you can use indexes 1 to n from this pointer.
int array[12];
int *array_starts_at_one = &array[-1]; // Don't use index 0 on this one
array_starts_at_one[1] = 1;
array_starts_at_one[12] = 12;
But I would advise against doing this.
Some more arguments why arrays are zero based can be found here. Infact its one of the very important and good features of the C programming language. However you can implement a array and start indexing from 1, but that will really take a lot of effort to keep track off.
Say you declare a integer array
int a[10];
for(i=1;i<10;i++)
a[i]=i*i;
You need to access all arrays with the index 1. Ofcourse you need to declare with the size (REQUIRED_SIZE_NORMALLY+1).
You should also note here that you can still access the a[0] element but you have to ignore it from your head and your code to achieve what you want to.
Another problem would be for the person reading your code. He would go nuts trying to figure out why did the numbering start from 1 and was the 0th index used for some hidden purpose which unfortunately he is unaware of.

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