简体   繁体   English

需要帮助来理解C中表达评估的顺序

[英]Need help in understanding order of evaluation of expression in C

I have troubles understanding how expression is evaluated in the below code. 我很难理解下面的代码如何评估表达式。 I do not understand how code works here 我不明白代码在这里如何工作

while (isdigit(s[++i] = c = getch()))
        ;

and why do we need 以及为什么我们需要

s[1] = '\0';

Full code 完整代码

#include <ctype.h>
int getch(void); 
void ungetch(int);
/* getop: get next character or numeric operand */ 

int getop(char s[])
{    
    int i, c;

    while ((s[0] = c = getch()) == ' ' || c == '\t');
    s[1] = '\0';

    if (!isdigit(c) && c != '.')
        return c; /* not a number */ 

    i = 0;

    if (isdigit(c)) /* collect integer part */ 
        while (isdigit(s[++i] = c = getch()));

    if (c == '.') /* collect fraction part */        
        while (isdigit(s[++i] = c = getch()));

    s[i] = '\0';
    if (c != EOF)
        ungetch(c);

    return NUMBER;    
}

Thank you for any help! 感谢您的任何帮助!

= is right associative and therefore isdigit(s[++i] = c = getch()) will be grouped as =正确关联,因此isdigit(s[++i] = c = getch())将被分组为
isdigit( s[++i] = (c = getch()) ) . isdigit( s[++i] = (c = getch()) ) getch will read and assign a char to c and then c is assigned to s[++i] . getch将读取一个char并将其分配给c ,然后将c分配给s[++i]

  1. This is the so called chained assignment, see wiki . 这就是所谓的链式分配,请参阅wiki To understand it, you only need to know that assignment in C has value! 要了解它,您只需要知道C中的赋值就是有价值的! Therefore, you can thing of it as equivalent to a one-liner of multiple successive assignment from right to left, as @hacks mentioned. 因此,就像@hacks所提到的,您可以将其等同于从右到左的多个连续分配的单线。

2. 2。

s[1] = '\0'; 

This is a safety concern and a normal coding practice: you always pad the end of a string with '\\0' in C. Since the input argument s[] is supposed to be a char array, thus you need to pad it. 这是一个安全问题,也是一种常规的编码实践:在C语言中,始终用'\\ 0'填充字符串的结尾。由于输入参数s []应该是char数组,因此需要对其进行填充。

Note that 注意

s[1] will be overwritten if s[0] is a digit or '.',

in which case the 2nd or 3rd while loop will be executed. 在这种情况下,将执行第二个或第三个while循环。 As before, you also need to pad the s[i] with '\\0'; 和以前一样,您还需要在s [i]上加上'\\ 0';

This whole function has a design flaw in that it is not possible to prevent a buffer overflow. 整个功能都有一个设计缺陷,即无法防止缓冲区溢出。 It needs to know the size of buffer that s is pointing to, to avoid that. 它需要知道s所指向的缓冲区的大小,以避免这种情况。

Anyway, while (isdigit(s[++i] = c = getch())); 无论如何, while (isdigit(s[++i] = c = getch())); has the same meaning as: 具有以下含义:

for (;;)
{
    ++i;
    c = getch();
    s[i] = c;

    if ( ! isdigit(s[i]) )
        break;
} 

There is a reason that c is used instead of just writing s[++i] = getch() . 使用c而不是只写s[++i] = getch()是有原因的。

Here I am assuming that getch (not a standard function) refers to some function which has the same return specification as getchar , ie it returns either unsigned char value or EOF . 在这里,我假设getch (不是标准函数)是指某个函数,该函数具有与getchar相同的返回规范,即它返回unsigned char值或EOF

The int c; int c; is needed so that EOF can be detected. 需要,以便可以检测到EOF If we did not have c then there is no way of performing the test if ( c != EOF ) at the end of the function. 如果我们没有c ,则无法在函数末尾执行if ( c != EOF )测试。 Doing s[i] == EOF would not work because it might mistake a valid character for EOF (or EOF might be out of range of char ). 进行s[i] == EOF无效,因为它可能会误认为EOF的有效字符(或者EOF可能超出char的范围)。

However the code still has a bug. 但是,代码仍然存在错误。 The isdigit function expects the same sort of int value; isdigit函数需要相同类型的int值; ie in my unpacked version, the final test should be: 即在我的解压缩版本中,最终测试应为:

if ( !isdigit(c) )

I'd guess that the code author knew about the issue with EOF but either didn't know about isdigit , or assumed his code would only be run on an implementation of it that accepted negative chars. 我猜想代码编写者知道EOF的问题,但要么不了解isdigit ,要么假设他的代码只能在接受负字符的实现上运行。

Writing it more compactly, the line could be replaced with: 编写得更紧凑,该行可以替换为:

i = 1;
// ...

while ( isdigit(c = getch()) )
    s[i++] = c;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM