IF的奇怪结果

时间:2016-03-03 10:30:51

标签: if-statement cmd

受到this question的启发及其答案,我做了一些测试。 一个答案表明,数字太大(超出32位整数)并且它们被截断,但这并不能解释结果。显然它也不会将双方都比作字符串(正如我所料)。似乎if感到困惑并认为“好吧,我不知道 - 给它一个真实的”。 (使用neqgtrlss代替equgeqleq总是假。)

如果a和/或b中的任何一个在32位整数的边界内或包含[0-9]中的任何char,则代码按预期工作。

@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 -)

对此有任何合理的解释,还是只是我们不得不考虑的事情?

2 个答案:

答案 0 :(得分:3)

此结果的原因可以在函数strtol的文档中找到,该函数首先用于使用比较运算符EQUNEQLSS,{{1 }},LEQGTR,正如我在Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files的回答中所解释的那样。

  

返回值
  成功时,该函数将转换后的整数作为long int值返回   如果无法执行有效转换,则返回零值(0L)   如果读取的值超出long int的可表示值范围,则函数返回LONG_MAX或LONG_MIN(在<climits>中定义),errno设置为ERANGE。

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

GEQ中的 IF 的编码类似于此C代码:

cmd.exe

将此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) { /* 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; } 的可执行文件,例如输出结果:

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

注意:错误编号和相应的错误字符串可能因使用的C编译器和标准库而异。

在两个测试用例中,两个参数在从string转换为long int时导致32位有符号整数溢出。因此,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) 返回了所有四个值strtol,并将LONG_MAX设置为errno。但溢出条件不是由ERANGE中的 IF 代码评估的。只需检查转换结果以及结束指针指向哪个字符的两个参数,如上面的C代码。

换句话说, IF 使用比较运算符cmd.exeEQUNEQLSSLEQGTR始终是一个整数比较,只要因为参数字符串中的无效字符,从字符串到整数的转换对于任何两个参数都不会失败。超出范围的条件不是 IF 没有进行整数比较的原因。

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

答案 1 :(得分:1)

这是一个限制。

StorageFile file = await StorageFile.GetFileFromPathAsync(ImageFilePath);
using (IRandomAccessStream fileStream = await File.OpenAsync(FileAccessMode.Read),
                                           memStream = new InMemoryRandomAccessStream())
  {
  // Open a Stream and decode a JPG image
  BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream);
  var softwareBitmap = await decoder.GetSoftwareBitmapAsync();

  byte [] imageBytes = new byte[4*decoder.PixelWidth*decoder.PixelHeight];
  softwareBitmap.CopyToBuffer(imageBytes.AsBuffer());
  //...  now you can use the imageBytes[]
}