这个结果的原因可以在
strtol函数的文档中找到,该函数首先使用比较运算符
EQU
、
NEQ
、
LSS
、
LEQ
、
GTR
和
GEQ
,如我在
Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files上的回答中所解释的那样。
返回值
成功时,该函数将转换后的整数作为long int值返回。
如果无法执行有效的转换,则返回值为零(0L)。
如果读取的值超出了long int可表示的范围,则函数返回LONG_MAX或LONG_MIN(定义在<climits>中),并且errno设置为ERANGE。
最后一句话是最重要的。
看起来cmd.exe
中的IF与此C代码类似:
#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)
{
lIntegerValue1 = strtol(argv[1],&pcEndValue1,0);
iErrorNumber1 = errno;
lIntegerValue2 = strtol(argv[2],&pcEndValue2,0);
iErrorNumber2 = errno;
if(((lIntegerValue1 == 0) && (*pcEndValue1 != '\0')) ||
((lIntegerValue2 == 0) && (*pcEndValue2 != '\0')))
{
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
{
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代码编译为控制台应用程序,并使用参数333333333333 444444444444
运行可执行文件的结果,例如输出:
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
的可执行文件,例如会产生如下输出:
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)
注意:错误编号和相应的错误字符串可能因所使用的C编译器或标准库而异。
在两个测试案例中,两个参数都导致从字符串转换为长整型时发生32位有符号整数溢出。因此,strtol
对所有四个值返回LONG_MAX
并将errno
设置为ERANGE
。但是,在cmd.exe
的IF代码中没有评估溢出条件。它只检查转换结果以及结束指针对于两个参数指向的字符,就像上面的C代码一样。
换句话说,只要由于参数字符串中存在无效字符而导致从字符串到整数的转换不失败,IF在使用比较运算符EQU
、NEQ
、LSS
、LEQ
、GTR
、GEQ
时总是进行整数比较。超出范围的情况不是IF
不执行整数比较的理由。
仅当两个参数字符串中有一个包含整数无效字符时才进行字符串比较。
cmd
工作方式的意义上 - 这意味着不是32位INT),我希望它被视为字符串处理)。echo on
明确显示没有截断或转换发生,因此似乎不是cmd
解析问题,而是if
本身的问题。 我想了解发生了什么以及为什么。 - Stephan