C-奇怪输出

时间:2017-05-21 13:53:47

标签: c pointers segmentation-fault command-line-arguments

所以我为一个简单的反向波兰计算器编写了一个代码,该计算器仅对正数使用命令行参数。它将数字存储在堆栈中。 push和pop的功能在一个单独的源文件中 我还写了另一个程序,检查我以前程序的控制流程 这是第一个程序:

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
void push(double);
double pop(void);
int main(int argc, char *argv[])
{
    int c;
    double op2;
    while(--argc>0 && (c=(*++argv)[0]))
        if(isdigit(c))
            push(atof(argv[0]));

        else if(c=='+')
            push(pop()+pop()); 

        else if(c=='-')
        {
            op2=pop();
            push(pop()-op2); 
        }

        else if(c=='*')
            push(pop() * pop()); 

        else
        {
            op2=pop();
            push(pop()/op2); 
        }

    printf("\n%f\n", pop());   
    return 0;
} 

运行此程序后,所有运算符都工作,除了'*'。例如,如果我的输入是'./pcalc 2 3 *',那么这就是我得到的输出:
error: stack emptyerror: stack emptyerror: stack emptyerror: stack empty -nan

如果我在while循环中交换条件,就像这样 while((c=(*++argv)[0]) && --argc>0)
然后我收到所有运营商的“分段故障(核心转储)”消息。

要知道我的程序的控制流程,我将部分代码更改为:

while(--argc>0 && (c=(*++argv)[0]))
    if(isdigit(c))
        printf("\nentry1\n");

    else if(c=='+')
        printf("\nentry2\n");

    else if(c=='-')
        printf("\nentry3\n");    

    else if(c=='*')
        printf("\nentry4\n");

    else
        printf("\nentry5\n");  

该计划的其余部分与第一部分类似。在输入'./pcalc 2 3 *'时,我得到了这个输出:

entry1

entry1

entry5

entry5

entry5

entry5

entry5
error: stack empty  
0.000000  

这意味着控制没有用于星号的情况,而是转到了其他部分 当我交换while循环的条件时,我得到的输出与上面类似(对于所有运算符,它显示控制流,对于'*',它显示与上面相同的错误),除了它,它没有不显示任何运算符的堆栈空错误,而是显示分段错误(核心转储)消息。

所以这就是我想问的问题:
1)我的第一个程序适用于所有操作员,除了'*'。可能是什么原因?控制权为什么要转到其他部分?

2)在交换条件后,我访问的内存是什么,我没有权限?如果它是NULL,那么不应该打破while循环并继续?

PS。这是我的第一个问题,所以如果我的写作风格有任何错误,或者问题太长,请告诉我!我们从错误中吸取教训:)
另外,我的编译器-GCC,OS-Ubuntu。

1 个答案:

答案 0 :(得分:1)

用户xing绝对正确。
要对其进行扩展,将从左到右对&&运算符进行求值。如果左侧条件无效,则不会评估正确的条件,因为已知返回值为0(假)。
运行./pcalc 2 3 *将扩展为./pcalc 2 3 <all the files/directories in current working directory>,因此它永远不会将操作员推送到运营商的堆栈上。

    在提取第一个元素之前,
  • while(--argc>0 && (c=(*++argv)[0]))将首先检查它是否仍在arguments数组中。
  • while((c=(*++argv)[0]) && --argc>0)将首先尝试提取值,然后检查它是否仍在数组的边界内。如果没有,那么它已经被分割了。