在 C 中为两个(一维)数组赋值



我正在尝试为两个数组页面和价格赋值。

#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]) 的第一个元素。 为什么会这样?

我了解建议对相关数据使用结构。但是,为什么会有这种奇怪的行为呢?

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

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

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

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

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

价格。。。。。。。。。。页

12 54 45 | 98 87 99

但是,当您尝试向页面和价格添加另一个元素时:

价格。。。。。。。。。。。。页

12 54 45 | 45 87 99 | 89

在这里,当您尝试输入 price[3] 时,它会获取 page[0] 的内存,因此它用 45 覆盖它,但在页面之后没有声明任何内容,因此 page[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;
}
    *

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

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

由于数组是立即连续定义的,并且出于对齐原因不需要填充,因此它们在内存中直接相邻。

所以:

  • 首先定义pages并在某个地址"创建"。
  • prices在此之后定义,并在下一个较小的可用地址创建。
  • 索引
  • 超出较低地址处对象的边界进入下一个对象的内存,朝向更高的地址。在堆栈上,这是之前定义的对象:
                           价格的第一要素,                                          地址 Y                                                         |                            |     最后一个元素                            |     的价格,                             |     地址 Y+2                            |        |                            五 五堆栈以这种方式增长 <- |---价格 ---|--- 页数 ----|地址以这种方式增长 -> |----|----|----|----|----|----|                                           ^         ^                                           |        |                                           |     的最后一个元素                                           |     页面、地址                                           |     x+2                                           |                                     第一个元素                                     页数,地址 x(即                                     y+3!这就是你写的!

从这个草图中可以合理地认为,当你访问prices+3,即紧靠prices上方的内存时,你最终访问了pages的第一个元素,它是在prices之前声明的,因此在堆栈上占据更高地址的内存。

通过越界索引访问内存是 C 中相当常见的错误,它不会(通常也不能)检查数组边界。这些错误可能是微妙的,不会被注意到,或者至少在很长一段时间内"不被理解"。如果你写到离原始对象更远的内存,你会覆盖存储在堆栈上的记账信息,就像返回地址一样,这通常会使程序崩溃(以一种难以找到崩溃位置的方式,因为该信息已被覆盖)。

相关内容

  • 没有找到相关文章

最新更新