需要帮助理解C中表达式的求值顺序吗

需要帮助理解C中表达式的求值顺序吗,c,C,我很难理解在下面的代码中表达式是如何计算的。 我不明白这里的代码是如何工作的 while (isdigit(s[++i] = c = getch())) ; 为什么我们需要 s[1] = '\0'; 完整代码 #include <ctype.h> int getch(void); void ungetch(int); /* getop: get next character or numeric operand */ int getop(char s[])

我很难理解在下面的代码中表达式是如何计算的。 我不明白这里的代码是如何工作的

while (isdigit(s[++i] = c = getch()))
        ;
为什么我们需要

s[1] = '\0';
完整代码

#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;    
}
#包括
int getch(无效);
无效未蚀刻(int);
/*getop:获取下一个字符或数字操作数*/
int getop(字符s[]
{    
int i,c;
而((s[0]=c=getch())==''| | c=='\t');
s[1]='\0';
如果(!isdigit(c)&&c!='。)
返回c;/*不是数字*/
i=0;
if(isdigit(c))/*收集整数部分*/
while(isdigit(s[++i]=c=getch());
如果(c=='。)/*收集分数部分*/
while(isdigit(s[++i]=c=getch());
s[i]='\0';
如果(c!=EOF)
未蚀刻(c);
返回号码;
}

谢谢你的帮助

=
是右关联的,因此
isdigit(s[++i]=c=getch())
将分组为

isdigit(s[++i]=(c=getch())
getch
将读取
char
并将其分配给
c
,然后
c
被分配给
s[++i]
=
是右关联的,因此
isdigit(s[++i]=c=getch())
将被分组为
isdigit(s[++i]=(c=getch())
getch
将读取
char
并将其分配给
c
,然后将
c
分配给
s[++i]

  • 这就是所谓的链式分配,请参见。要理解它,您只需要知道C中的赋值有值!因此,正如@hacks所提到的,您可以将它看作是从右到左的多个连续赋值的一行
  • 二,

    这是一个安全问题,也是一种正常的编码实践:在C中,总是用“\0”填充字符串的结尾。由于输入参数s[]应该是一个字符数组,因此需要填充它

    注意

    s[1] will be overwritten if s[0] is a digit or '.',
    
    在这种情况下,将执行第二个或第三个while循环。与前面一样,您还需要用“\0”填充s[i]

  • 这就是所谓的链式分配,请参见。要理解它,您只需要知道C中的赋值有值!因此,正如@hacks所提到的,您可以将它看作是从右到左的多个连续赋值的一行
  • 二,

    这是一个安全问题,也是一种正常的编码实践:在C中,总是用“\0”填充字符串的结尾。由于输入参数s[]应该是一个字符数组,因此需要填充它

    注意

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

    在这种情况下,将执行第二个或第三个while循环。与前面一样,您还需要用“\0”填充s[i]

    整个函数都有一个设计缺陷,无法防止缓冲区溢出。它需要知道
    s
    所指向的缓冲区的大小,以避免这种情况

    无论如何,
    while(isdigit(s[++i]=c=getch())的含义与:

    for (;;)
    {
        ++i;
        c = getch();
        s[i] = c;
    
        if ( ! isdigit(s[i]) )
            break;
    } 
    
    使用
    c
    而不是仅仅编写
    s[++i]=getch()
    是有原因的

    这里我假设
    getch
    (非标准函数)指的是与
    getchar
    具有相同返回规范的函数,即它返回
    无符号char
    值或
    EOF

    intc,以便可以检测到
    EOF
    。如果没有
    c
    ,则无法在函数末尾执行测试
    If(c!=EOF)
    。执行
    s[i]==EOF
    将不起作用,因为它可能会将有效字符误认为
    EOF
    (或者
    EOF
    可能超出
    char
    的范围)

    然而,代码仍然有一个bug。
    isdigit
    函数需要相同类型的
    int
    值;i、 e.在我的未包装版本中,最终测试应为:

    if ( !isdigit(c) )
    
    我猜代码作者知道关于
    EOF
    的问题,但要么不知道
    isdigit
    ,要么假设他的代码只能在接受负字符的实现上运行

    如果写得更紧凑,可以用以下内容替换该行:

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

    整个函数都有一个设计缺陷,即无法防止缓冲区溢出。它需要知道
    s
    所指向的缓冲区的大小,以避免这种情况

    无论如何,
    while(isdigit(s[++i]=c=getch())的含义与:

    for (;;)
    {
        ++i;
        c = getch();
        s[i] = c;
    
        if ( ! isdigit(s[i]) )
            break;
    } 
    
    使用
    c
    而不是仅仅编写
    s[++i]=getch()
    是有原因的

    这里我假设
    getch
    (非标准函数)指的是与
    getchar
    具有相同返回规范的函数,即它返回
    无符号char
    值或
    EOF

    intc,以便可以检测到
    EOF
    。如果没有
    c
    ,则无法在函数末尾执行测试
    If(c!=EOF)
    。执行
    s[i]==EOF
    将不起作用,因为它可能会将有效字符误认为
    EOF
    (或者
    EOF
    可能超出
    char
    的范围)

    然而,代码仍然有一个bug。
    isdigit
    函数需要相同类型的
    int
    值;i、 e.在我的未包装版本中,最终测试应为:

    if ( !isdigit(c) )
    
    我猜代码作者知道关于
    EOF
    的问题,但要么不知道
    isdigit
    ,要么假设他的代码只能在接受负字符的实现上运行

    如果写得更紧凑,可以用以下内容替换该行:

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

    检查一下@EJEHardenberg,螺旋规则适用于类型声明,而不是表达式和操作顺序:在调用者中用作字符串的保险。使用
    c
    和分配链接是为了优化代码,其思想是<