将值赋给C中的两个(一维)数组

时间:2016-01-26 11:40:17

标签: c arrays

我正在尝试将值分配给两个数组Pages和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;
}

输出如下:

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

这里,输入的最后一个元素的值,即(price [3] = 89)被分配给数组Pages(pages [0])的第一个元素。为什么会这样?

据我所知,建议对相关数据使用struct。但是,为什么这种奇怪的行为呢?

4 个答案:

答案 0 :(得分:3)

您的情况是i <= 33也符合这一要求。因此,将访问pages[3]pages[3],这在两种情况下都是未定义的行为。索引从C中的0开始,因此具有x元素的数组在[0; x - 1]中具有明确定义的索引。

将条件更改为i < 3以解决问题并使程序定义明确。

答案 1 :(得分:1)

你的阵列只有3个元素的空间,所以你要经过一个结束。 将它们放大或更改循环以使用<而不是<=

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

答案 2 :(得分:1)

通常,当我们声明任何变量或数组时,它们会使内存彼此接近或相继接近。在这种情况下,当您声明价格和页面时,它们会在前三个元素之后获得内存:

价格..........页

12 54 45 | 98 87 99

但是当你尝试将另一个元素添加到页面和价格时:

价格............页

12 54 45 | 45 87 99 | 89

这里当你试图输入价格[3]时,它获取了页面[0]的内存,所以它用45覆盖它,但是后面的页面没有声明,所以页面[3]从外部获取内存并且没有覆盖任何东西。

尝试运行此代码,您的疑问将会消除:

*

#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;
}
    *

答案 3 :(得分:0)

正如其他人所说,写作 - 甚至是阅读! - 超出数组(或一般对象)的界限是一个严重的错误。但是,程序暴露的行为实际上是非常期待的,并且对程序的内存布局有一点了解。

您的数组是局部变量,具有&#34;自动存储持续时间&#34;,vulgo:它们在堆栈上分配。在您的实现中(我认为这是C实现的标准),堆栈朝着更小的地址发展。稍后定义的对象驻留在较低地址的内存中:首先定义pages,然后prices - prices在内存中较低。 (但每个数组中的 元素都必须从低地址到高地址排列。原因是对于任何数组arrarr[i]等同于{ {1}},其中总和确实为*(arr+i)的数字地址添加了一个值,因此该元素的地址高于arr的正arr地址。)

由于您的阵列已经立即连续定义,并且由于对齐原因不需要填充,因此它们在内存中直接相邻。

所以:

    首先定义
  • i,然后创建&#34;&#34;在某个地址。
  • pages在此之后定义,并在下一个较小的可用地址创建。
  • 索引超出较低地址的对象范围 进入更高地址的下一个对象的记忆。在堆栈上,这是之前定义的对象:
                            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!)

从这个草图中可以看出,当您访问prices时,即prices+3上方的内存时,您最终会访问prices的第一个元素,该元素在pages之前被声明{1}}因此占用堆栈上更高地址的内存。

通过越界索引访问内存是C中相当常见的错误,它不会 - 通常也不能 - 检查数组边界。这些错误可能是微妙的,而且不会引起注意,或者至少是“不被理解的”#34;需很长时间。如果你甚至远离原始对象写入内存,你会通过像返回地址这样的实现覆盖存储在堆栈中的簿记信息,这通常会导致程序崩溃(这种方式很难找到崩溃位置,因为该信息已被覆盖)。