为什么编译器显示意外结果?

时间:2015-07-18 19:12:23

标签: c arrays

我是编程新手。目前正在学习C语言。我现在很困惑一个在跑步后出现意外结果的问题。

问题是 -

我想创建一个程序,比用户输入ABC.age = 21 时更多地输入输入并停止输入后输入并打印用户在42之前键入的所有数字。

例如 - 输入:

42

输出:

1
2
88
42
99

我的计划 -

1
2
88

当我输入与例子中相同的值时,我得到意想不到的结果,如 -

#include <stdio.h>

int main()
{
    int i = 1, j, temp;

    printf("enter numbers:\n");
    while (i)
    {
        scanf("%d", &temp);
        i++;

        int a[i];

        a[i - 2] = temp;
        if (temp == 42)
        {
            scanf("%d", &a[i - 1]);
            for (j = 0 ; j < i - 1 ; j++)
            {
                if (a[j] == 42)
                    break;
                else 
                    printf("%d\n",a[j]);
            }        
        }
        if (temp == 42)
            break;
    }    
    return 0;
}

请帮忙。对不起我的英语不好。提前谢谢。

4 个答案:

答案 0 :(得分:1)

您正在打印未初始化的值,因为如果i的值变为3且值更大,则您永远不会设置a[0]以及a[i - 2]之前的所有值。

因此在以下行导致Undefined Behavior

printf("%d\n", a[j]);

某些值未初始化,您仍尝试打印它们。

您应该注意到a在每次迭代时都被重新声明,并且您没有初始化值,因为前一个a中的值仅在上一次迭代中有效。

a变量仅在while循环的范围内有效,但不仅因为它未在外部声明,还因为它在超出范围时被释放。也许一个例子会让它更清晰。

假设您有以下程序

int main(void)
{
    int *pointer = NULL;
    if (pointer == NULL)
    {
        int array[5] = {1, 2, 3, 4, 5};
        pointer = array;
    }
    /* `poitner' points to `array` but array was deallocated */
    for (int i = 0 ; i < 5 ; ++i)
        printf("%d\n", pointer[i]); /* This is UB */
    return 0;
}

这会编译,但是你可以看到它会调用未定义的行为。

由于无法理解代码的作用,我建议如下

#include <stdio.h>

int main()
{
    int i = 1;
    int a[100];

    printf("enter numbers:\n");
    while (i++ < 100)
    {
        if (scanf("%d%*c", &a[i - 2]) != 1)
            return -1; /* this was invalid input, it will cause UB */
        if (a[i - 2] == 42)
        {
            if (scanf("%d%*c", &a[i - 1]) != 1)
                return -1; /* this was invalid input, it will cause UB */
            for (int j = 0 ; j < i - 1 ; j++)
            {
                if (a[j] == 42)
                    break;
                else
                    printf("%d\n", a[j]);
            }
        }

        if (a[i - 2] == 42)
            break;
    }

    return 0;
}

这至少可以消除恶意行为并使代码更具可读性,但目前还不清楚这个程序是什么或它应该做什么。

答案 1 :(得分:0)

一般情况下,由于输入值的数量未知,您需要为新输入的值动态分配存储空间。

所以我会建立一个包含输入值的列表。另一种方法是在输入新值时对整个数组使用<h1>404 - Page not found</h1> malloc。在我看来,这比建立一个列表更糟糕。

程序可以按以下方式查看

realloc

如果要输入以下值

#include <stdio.h>
#include <stdlib.h>

int main( void )
{
    struct node
    {
        int value;
        struct node *next;
    } * head = NULL;

    struct node **current = &head;
    int value;

    int next = -1;

    while ( next != 1 && scanf( "%d", &value ) == 1 )
    {
        if ( next == 0 || value == 42 ) ++next;

        if ( next == -1 )
        {            
            *current = malloc( sizeof( struct node ) );
            ( *current )->value = value;
            ( *current )->next  = NULL;
            current = &( *current )->next;
        }
    }

    while ( head )
    {
        printf( "%d\n", head->value );
        struct node *tmp = head;
        head = head->next;
        free( tmp );
    }        
}    

然后程序输出

1 2 3 4 5 6 7 8 9 42 10

该列表在42之后既不存储42也不存储下一个值,但您可以修改程序以便存储这些值。

至于你的代码,至少这句话

1
2
3
4
5
6
7
8
9
当i等于1时,

错误,导致程序的行为未定义。 我不认为我会被改变。

答案 2 :(得分:-1)

你正在做一些不必要的事情。 你必须检查一下 -

while(input_number)
{
    if(input_number==42)
      break;
    else
      printf("%d\n",input_number);
}

在我的想法中,我根据您的代码编辑了代码,以便在42之前存储所有数字。

#include<stdio.h>
int main()
{
    int i=1,j,temp;
    int a[10010];
    printf("enter numbers:\n");
    while(i)
    {
        scanf("%d",&temp);
        i++;
        a[i-2]=temp;
        if(temp==42)
        {
            for(j=0; j<i-2; j++)
            {
                if(a[j]==42)
                    break;
                else
                    printf("%d\n",a[j]);
            }

        }
        if (temp == 42)
            break;
    }

    return 0;
}

答案 3 :(得分:-1)

我认为你的问题是试图用不同的值多次声明(和重新声明)a [i]。编译器需要在编译时知道数组的大小。因此,编译器为具有一个元素的整数数组预留内存,然后代码的动态部分尝试将其重新声明为运行时。尝试移动while循环外部并使用明确定义的最大整数值来声明它,如:

#define MAX_NUMS 1000

int a[MAX_NUMS];

上面列出了一些其他问题,但是我使用GCC 4.9编译器进行了测试,它似乎给出了预期的结果。