assigning values to two (one dimensional) arrays in C

I am trying to assign values to two arrays Pages and Price.

#include<stdio.h>
int main()
{
    static int pages[3];
    static int price[3];
 int i;
 printf("\nEnter the no. of pages and price of the book:\n");
 for (i=0; i<=3; i++)
 {  
    printf("provide input:");
    scanf(" %d %d", &pages[i], &price[i]);
 }
for (i=0; i<=3; i++)
{
    printf(" %d %d", pages[i], price[i]);
}
getch();
return 0;
}

The output is as follows:

Enter the no. of pages and price of the book:
Provide Input:98
12
Provide Input:87
54
Provide Input:99
34
Provide Input:89
45

45 12 87 54 99 34 89 45

Here, the value of the last element that is entered i.e, (price[3]=89) gets assigned to the first element of the array Pages (pages[0]). Why does this happen?

I understand that it is recommended to use struct for related data. But, why is this weird behavior?

Answers


Your condition is i <= 3. 3 also fulfills this. Therefore, pages[3] and pages[3] will be accessed, which is undefined behavior in both cases. Indexing starts at 0 in C, so an array with x elements has well-defined indices in [0; x - 1].

Change the condition to i < 3 to resolve the problem and render your program well-defined.


Your arrays only have room for 3 elements, so you're going one past the end. Make them bigger or change your loops to use < rather than <= :

for (i=0; i < 3; i++)
{  
    /* Do things with pages[i] and price[i] */
}

Generally when we declare any variable or array they get memory close by or after one another. In this case when you declare price and pages they get memory after one another for the first three elements:

price..........page

12 54 45 | 98 87 99

But when you try to add another element to page and price:

price............page

12 54 45 | 45 87 99 | 89

here when you try to enter price[3] it gets the memory of page[0] so it overrides it with 45 but as after page nothing is declared so page[3] gets memory from outside and doesn't override anything.

try running this code your doubt will clear up:

*

#include<stdio.h>

int main()
{
     static int pages[3];
     static int price[3];
 int i;
 printf("\nEnter the no. of pages and price of the book:\n");
 for (i=0; i<=3; i++)
 {  
    printf("provide input:");
    scanf(" %d %d", &pages[i], &price[i]);
 }
for (i=0; i<=3; i++)
{
    printf(" %d %d", &pages[i], &price[i]);
}
printf("\n");
for (i=0; i<=3; i++)
{
    printf(" %d %d", pages[i], price[i]);
}
getch();
return 0;
}
    *

As the others said, writing -- even reading! -- beyond the bounds of an array (or object in general) is a severe error. But the behavior your program exposed is actually quite expected with a little knowledge about the memory layout of a program.

Your arrays are local variables with "automatic storage duration", vulgo: they are allocated on the stack. In your implementation (and I think that this is the standard for C implementations) the stack grows towards smaller addresses. Objects which are defined later reside in memory at lower addresses: pages is defined first, and then prices -- prices is lower in memory. (But the elements inside each array are arranged, as they must be, from lower to higher addresses. The reason is that for any array arr, arr[i] is equivalent to *(arr+i), where the summation indeed adds a value to the numerical address of arr, so that the element is at a higher address than arr for positivei.)

Because your arrays have been defined in immediate succession and no padding is necessary for alignment reasons, they are directly adjacent in memory.

So:

  • pages is defined first and "created" at some address.
  • prices is defined after that and is created at the next smaller available address.
  • indexing beyond the bounds of an object at the lower address intrudes into the memory of the next object towards higher addresses. On the stack this is the object defined before:
                            first element of prices,               
                            address y                              
                            |
                            |      last element
                            |      of prices,  
                            |      address y+2 
                            |         |
                            V         V
stack grows this way    <- |--- prices ---|--- pages ----|
addresses grow this way -> |----|----|----|----|----|----|
                                           ^         ^
                                           |         |
                                           |      last element of
                                           |      pages, address
                                           |      x+2
                                           |
                                     first element
                                     of pages, address x (i.e. 
                                     y+3! This is what you write to!)

From this sketch it should be plausible that when you access prices+3, i.e. the memory immediately above prices, you end up accessing the first element of pages, which was declared before prices and therefore occupies memory at a higher address on the stack.

Accessing memory through out-of-bounds indices is a fairly common error in C which does not -- and in general cannot -- check array bounds. The errors can be subtle and go unnoticed or at least "un-understood" for a long time. If you write to memory even further away from your original object you overwrite book-keeping information stored on the stack by the implementation like return addresses, which will ususally make a program crash (in a fashion which makes it difficult to find the crash location, since that information has been overwritten).


Need Your Help

MySQL: sort list of values before use it in the query

mysql sql md5

Can I sort list of values before use it in the query?