C fscanf 添加一个元素到数组,不应该

标签 c

#include <stdio.h>


int main() {

    FILE *input;
    FILE *output;

    input = fopen("algsort.in", "r");
    output = fopen("algsort.out", "w");

    int n = 0;
    fscanf(input, "%d", &n);        // reads n = 7

    int i;
    int a[6] = {1, -1, 0, 33, 6, 5};


    for(i = 0; i < 8; i++) {     // 8 is on purpuse
        printf("%d  ", a[i]);    // the output is [1 -1 0 33 6 5 7 $(Random location in memory)]
    }


    return 0;
}

fscanf 在数组末尾追加一个元素。这是一个问题,因为它干扰了排序算法,遗漏了一个大于 n 的元素。 我知道 for 循环的限制,问题是,“n”元素仍然是数组的一部分。 问题:7 是从哪里来的?

最佳答案

fscanf appends an element at the end of the array.

不,它没有。您的数组仍然是六个 int 的数组。您可以越过数组末尾而不会崩溃的事实并不意味着您的数组以某种方式获得了一个额外的元素 - 这意味着这次未定义的行为没有导致崩溃。

Where did the 7 come from?

从内存中 sizeof(int) 的位置开始,经过数组 a 的末尾。通过数组访问此位置是未定义的行为,因此可以返回任何值。 A quick experiment shows至少有一个编译器可以以 n 直接位于数组 a 之后的方式在您的函数中布置内存:

FILE *input = NULL;
FILE *output = NULL; 
int n = 0;
scanf("%d", &n); // reads n = 7
int a[6] = {1, -1, 0, 33, 6, 5};
printf("%p\n%p\n", (void*)&n, (void*)&a[6]);

这打印

0xbfabd5e4
0xbfabd5e4

这意味着 n 的地址和 a+6 的值(当你取消引用数组末尾的一个元素时得到的)指向到同一个地址。如果你的编译器做同样的事情,你会看到同样的结果。即使是这种情况,此行为仍未定义。

关于C fscanf 添加一个元素到数组,不应该,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26389139/

相关文章:

c - 这是解决循环 typedef 依赖的正确方法吗?

c - 16 位机器上可以使用 32 位整数吗?

c - 将字符串转换为二维数组时,第一个元素被损坏

c - GCC 编译非常慢(大文件)

char [] 和 sprintf 段错误

c - 关于c程序的调试

c - if 字符串比较语句未正确执行

c - 标准输出重定向因 wprintf() 而失败

Android NDk 和 CLI

c - 将键盘事件保存到带有图形窗口的数组中