中频的结果很奇怪 [英] weird results with IF

查看:56
本文介绍了中频的结果很奇怪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题的启发,它的答案是,我做了一些测试。
一个答案表明,数字太大(超出32位整数)并且被截断了,但这并不能解释结果。同样显然,它并没有将双方都比较为字符串(正如我所期望的那样)。似乎 if 感到困惑,并认为好吧,我不知道-给它一个TRUE。 (使用 neq gtr lss 代替 equ geq leq 始终为FALSE)。

Inspired by this question and it's answers, I did some testing. One answer suggests, the numbers are too big (out of 32bit integer) and they get truncated, but this doesn't explain the results. Also obviously it doesn't compare both sides as strings (as I would have expected). It seems that if gets confused and thinks "well, I don't know - give it a TRUE". (Using neq, gtr, lss instead of equ, geq, leq always give FALSE).

如果 a 和/或 b 在32位整数的边界内或包含[0-9]中的任何字符。

The code works as expected, if any of a and/or b are within the borders of 32bit integer or contain any char out of [0-9].

@echo off
set a=333333333333
set b=444444444444
call :compare
set b=222222222222
call :compare
goto :eof

:compare
echo comparing %a% with %b%
if %a% geq %b% (echo a ^>= b) else (echo -)
if %b% geq %a% (echo b ^>= a) else (echo -)
if %a% leq %b% (echo a ^<= b) else (echo -)
if %b% leq %a% (echo b ^<= a) else (echo -)
if %a% equ %b% (echo a  = b) else (echo -)
if %a% == %b% (echo a == b) else (echo -)

对此是否有任何合乎逻辑的解释,或者这仅仅是我们必须不加思索地生活的东西?

Is there any logical explanation for this, or is it just something we have to live with without thinking?

推荐答案

此结果的原因可以在函数 strtol ,它首先用于使用比较运算符 EQU NEQ LSS LEQ GTR GEQ ,如我在与Windows批处理文件中的NEQ,LSS,GTR等等效的符号

The reason for this result can be found in documentation of function strtol which is used first on using the comparison operators EQU, NEQ, LSS, LEQ, GTR, GEQ as explained in my answer on Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files.


返回值

成功后,该函数将转换后的整数返回为long int值。

如果无法执行有效的转换,则返回零值(0L)。 br>
如果读取的值超出long整数可表示的值的范围,则该函数返回LONG_MAX或LONG_MIN(在< climits> ),并且 errno 设置为ERANGE

Return Value
On success, the function returns the converted integral number as a long int value.
If no valid conversion could be performed, a zero value is returned (0L).
If the value read is out of the range of representable values by a long int, the function returns LONG_MAX or LONG_MIN (defined in <climits>), and errno is set to ERANGE.

最后一句话在这里最重要。

The last sentence is most important here.

cmd.exe 中的 IF 的编码类似于以下C代码:

It looks like IF in cmd.exe is coded similar to this C code:

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

int main (int argc, char* argv[])
{
    const char csNo[] =  "no";
    const char csYes[] = "yes";

    char* pcEndValue1;
    char* pcEndValue2;
    int   iExitCode = 2;
    int   iErrorNumber1;
    int   iErrorNumber2;
    int   iStringResult1;
    int   iStringResult2;
    long  lIntegerValue1;
    long  lIntegerValue2;

    if(argc > 2)
    {
        /* Convert the two arguments to 32-bit signed integers. */
        lIntegerValue1 = strtol(argv[1],&pcEndValue1,0);
        iErrorNumber1 = errno;
        lIntegerValue2 = strtol(argv[2],&pcEndValue2,0);
        iErrorNumber2 = errno;

        /* Failed the conversion for any of the two arguments? */
        if(((lIntegerValue1 == 0) && (*pcEndValue1 != '\0')) ||
           ((lIntegerValue2 == 0) && (*pcEndValue2 != '\0')))
        {
            /* Compare case-sensitive the two arguments as strings. */
            iStringResult1 = strcmp(argv[1],argv[2]);
            iStringResult2 = strcmp(argv[2],argv[1]);

            printf("String comparing %s (a) with %s (b):\n\n",argv[1],argv[2]);
            printf("a GEQ b: %s\n",(iStringResult1 >= 0) ? csYes : csNo);
            printf("b GEQ a: %s\n",(iStringResult2 >= 0) ? csYes : csNo);
            printf("a LEQ b: %s\n",(iStringResult1 <= 0) ? csYes : csNo);
            printf("b LEQ a: %s\n",(iStringResult2 <= 0) ? csYes : csNo);
            printf("a EQU b: %s\n",(iStringResult2 == 0) ? csYes : csNo);
            iExitCode = 1;
        }
        else
        {
            /* Compare the values. */
            printf("Value comparing %s/%ld (a) with %s/%ld (b):\n\n",argv[1],lIntegerValue1,argv[2],lIntegerValue2);
            printf("a GEQ b: %s\n",(lIntegerValue1 >= lIntegerValue2) ? csYes : csNo);
            printf("b GEQ a: %s\n",(lIntegerValue2 >= lIntegerValue1) ? csYes : csNo);
            printf("a LEQ b: %s\n",(lIntegerValue1 <= lIntegerValue2) ? csYes : csNo);
            printf("b LEQ a: %s\n",(lIntegerValue2 <= lIntegerValue1) ? csYes : csNo);
            printf("a EQU b: %s\n",(lIntegerValue2 == lIntegerValue1) ? csYes : csNo);
            iExitCode = 0;
        }
        printf("\nError number a: %d ... %s\n",iErrorNumber1,strerror(iErrorNumber1));
        printf("Error number b: %d ... %s\n",iErrorNumber2,strerror(iErrorNumber2));
    }
    return iExitCode;
}

将此C代码编译为控制台应用程序并使用参数<$运行可执行文件c $ c> 333333333333 444444444444 结果例如在输出中

Compiling this C code as console application and running the executable with the parameters 333333333333 444444444444 results for example in output:

Value comparing 333333333333/2147483647 (a) with 444444444444/2147483647 (b):

a GEQ b: yes
b GEQ a: yes
a LEQ b: yes
b LEQ a: yes
a EQU b: yes

Error number a: 2 ... Output of function out of range (ERANGE)
Error number b: 2 ... Output of function out of range (ERANGE)

并使用参数 333333333333 222222222222 运行可执行文件例如,输出结果:

And running the executable with the parameters 333333333333 222222222222 results for example in output:

Value comparing 333333333333/2147483647 (a) with 222222222222/2147483647 (b):

a GEQ b: yes
b GEQ a: yes
a LEQ b: yes
b LEQ a: yes
a EQU b: yes

Error number a: 2 ... Output of function out of range (ERANGE)
Error number b: 2 ... Output of function out of range (ERANGE)

注意:错误号

在两个测试案例中,两个参数都导致从字符串转换时导致32位有符号整数溢出到长整数。因此,对于所有四个值 LONG_MAX 返回了 strtol 并设置了 errno ERANGE 。但是溢出条件不会由 cmd.exe 中的 IF 代码评估。就像上面的C代码一样,只需检查转换结果以及两个参数的结束指针指向哪个字符。

In both test cases both arguments resulted in a 32-bit signed integer overflow on conversion from string to long int. Therefore strtol returned for all four values LONG_MAX and set errno to ERANGE. But the overflow condition is not evaluated by code of IF in cmd.exe. It is just checked the conversion result and on which character the end pointer points to for both arguments like by the C code above.

换句话说,就是 IF EQU , NEQ LSS LEQ GTR GEQ 始终是整数只要两个参数中的任何一个从字符串到整数的转换都不会失败,因为参数字符串中的字符无效。超出范围的条件并不意味着 IF 不进行整数比较。

In other words IF processes on usage of comparison operators EQU, NEQ, LSS, LEQ, GTR, GEQ always an integer comparison as long as conversion from string to integer does not fail for any of the two arguments because of an invalid character in argument strings. An out of range condition is no reason for IF not doing an integer comparison.

仅当两个参数之一进行字符串比较时,字符串包含无效的整数字符。

A string comparison is done only if one of the two argument strings contains an invalid character for an integer.

这篇关于中频的结果很奇怪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆