【发布时间】:2017-12-13 20:17:21
【问题描述】:
我有一个用于在大学课程中测试 C 程序的脚本。我使用 VS2015 的开发人员命令提示符编译学生的文件,只需运行命令 cl file.c。但是,我发现在某些(非常罕见的)情况下,与在 VS2015 上运行这些程序相比,我得到不同的输出(我们指导学生在该 IDE 中检查他们的程序)。 经过一番调查,我发现当我包含头 (.h) 文件时会发生这种情况(请参见下面的代码示例)。
cl 实际上是 VS2015 使用的同一个编译器吗?如果是 - 那我怎么会得到不同的结果。如果不是 - 我应该给出什么命令才能获得类似的结果?
代码示例 - 运行应评估数学字符串的函数的程序。评估是从左到右进行的,而不考虑普通的数学顺序优先级:
test_data.h
#ifndef _TEST_DATA_H
#define _TEST_DATA_H
char *mathString2 = "64 / 8 * 8 - 8 / 8 / 8 / 8 * 8 * 8 * 8";
#endif /* _TEST_DATA_H */
test.c
#include <stdio.h>
#include "test_data.h"
// Q1
double string2uint(char str[])
{
int i = 0;
double res = 0;
while (str[i] != '\0') {
res = res * 10 + (str[i] - '0');
i++;
}
return res;
}
void calcMathString(char mathString[])
{
int i, j = 0;
double e = 0;
char t = '+', str_n[101];
for (; mathString[j] != '\0'; j++)
{
i = 0;
while (mathString[j] != '\0') {
str_n[i] = mathString[j];
if (mathString[j] == ' ')
{
str_n[i] = '\0';
i++;
j++;
break;
}
if (mathString[j + 1] == '\0')
{
i++;
str_n[i] = '\0';
j++;
break;
}
i++;
j++;
}
if (t == '+') {
e = e + string2uint(str_n);
}
if (t == '-') {
e = e - string2uint(str_n);
}
if (t == '*') {
e = e*string2uint(str_n);
}
if (t == '/') {
e = e / string2uint(str_n);
}
t = mathString[j];
j = j + 1;
}
printf("%s = %.3lf\n", mathString, e);
}
int main()
{
char *mathString1 = "64 / 8 * 8 - 8 / 8 / 8 / 8 * 8 * 8 * 8";
calcMathString(mathString1);
calcMathString(mathString2);
return 0;
}
注意mathString1, mathString2 是相同的。
我用cl 编译的输出:
64 / 8 * 8 - 8 / 8 / 8 / 8 * 8 * 8 * 8 = 56.000
64 / 8 * 8 - 8 / 8 / 8 / 8 * 8 * 8 * 8 = 48.000
我在 VS 中运行时得到的输出:
64 / 8 * 8 - 8 / 8 / 8 / 8 * 8 * 8 * 8 = 56.000
64 / 8 * 8 - 8 / 8 / 8 / 8 * 8 * 8 * 8 = 56.000
【问题讨论】:
-
VS 有很多项目设置,您可能希望通过特定的
cl参数来模仿这些设置,以获得完全相同的二进制文件。 -
我如何知道这些参数?我希望我的命令行
cl编译的行为与 VS 一样。 -
但这并不重要,因为不同的结果表明代码中有一些未定义的行为,应该修复。
-
尝试
char *mathString2 = "64 / 8 * 8 - 8 / 8 / 8 / 8 * 8 * 8 * 8\0" "1111";查看代码是否越界访问。 -
if (mathString[j + 1] == '\0')可以访问字符串外部,因为之前的指令已经增加了j。用一个空格结束你的字符串,你可能会遇到这个问题。
标签: c visual-studio-2015 compilation cl