微软开发的MSVC编译器(cl.exe)本质上是一种C++语言编译器,编译C语言源程序只是它的一个附属功能。有一些C语言中的标准库函数在C++中几乎不使用,微软就会将这些函数标记为“弃用”,并在编译时给出警告信息(新版本会给出错误信息),这个警告/错误的代码就是C4996。
例如:输入数据时,C++使用的是
int a;
std::cin >> a;
而不是C语言中的:
int a;
scanf ("%d", &a);
所以微软就会在C++的编译过程中弃用scanf函数。
又例如:C++有字符串类型,可以直接进行字符串变量之间的赋值操作:
std::string str1 = "Hello, world!", str2;
str2 = str1;
以上代码可以直接将str1的值赋给str2。然而C语言没有字符串类型,只能用以下方法实现此功能:
char *str1 = "Hello, world!", *str2 = (char [100]){};
strcpy (str2, str1);
由此可见:C++由于原生支持字符串类型,不需要通过字符数组或字符指针存储字符串,所以strcpy这类函数也就没有用武之地了。C++就可以弃用strcpy这个函数了。
如果微软只在C++的编译过程中适用这种“弃用”规则,还不会引起很大的问题。然而微软在C语言的编译过程中也强行把C++中的这种“弃用”规则照搬过来,导致了一批C语言中的标准库函数缺失,并且没有替代函数。在这种背景之下,微软造了一些只能用于MSVC的函数代替标准库函数。举个例子:标准库函数为scanf,微软自己的叫做scanf_s;微软强行规定scanf_s在输入字符串时必须指定第三个参数。如标准库函数写作:
char str[100];
scanf ("%99[^\n]", str);
要改写成:
char str[100];
scanf_s ("%[^\n]", str, 100);
才能在MSVC上通过编译。
这些微软自己造的函数只能在Windows平台上使用,Linux等其他操作系统一概不支持。也就是说微软自己造的这些函数不能跨平台使用。
类似的问题还有:以下C语言程序是没有语法错误的
#include <stdio.h>
int main (void) {
int n;
scanf ("%d", &n);
int a[n];
for (int i = 0; i < n; i++) {
scanf ("%d", a + n - 1 - i);
}
for (int i = 0; i < n; i++) {
printf ("%d", a[i]);
putchar ((i < n - 1) ? ' ' : '\n');
}
return 0;
}
然而在MSVC中,这段程序在编译时会产生“表达式必须含有常量值”的编译错误。这是因为C++不支持VLA,MSVC在编译C程序时会拒绝这种与C++标准不一致的C语言特性。
综上,编译C语言程序时不要使用MSVC,可以使用MinGW GCC或LLVM Clang等编译器。新版的VS可以在VS安装程序内安装Clang编译器。
例如:输入数据时,C++使用的是
int a;
std::cin >> a;
而不是C语言中的:
int a;
scanf ("%d", &a);
所以微软就会在C++的编译过程中弃用scanf函数。
又例如:C++有字符串类型,可以直接进行字符串变量之间的赋值操作:
std::string str1 = "Hello, world!", str2;
str2 = str1;
以上代码可以直接将str1的值赋给str2。然而C语言没有字符串类型,只能用以下方法实现此功能:
char *str1 = "Hello, world!", *str2 = (char [100]){};
strcpy (str2, str1);
由此可见:C++由于原生支持字符串类型,不需要通过字符数组或字符指针存储字符串,所以strcpy这类函数也就没有用武之地了。C++就可以弃用strcpy这个函数了。
如果微软只在C++的编译过程中适用这种“弃用”规则,还不会引起很大的问题。然而微软在C语言的编译过程中也强行把C++中的这种“弃用”规则照搬过来,导致了一批C语言中的标准库函数缺失,并且没有替代函数。在这种背景之下,微软造了一些只能用于MSVC的函数代替标准库函数。举个例子:标准库函数为scanf,微软自己的叫做scanf_s;微软强行规定scanf_s在输入字符串时必须指定第三个参数。如标准库函数写作:
char str[100];
scanf ("%99[^\n]", str);
要改写成:
char str[100];
scanf_s ("%[^\n]", str, 100);
才能在MSVC上通过编译。
这些微软自己造的函数只能在Windows平台上使用,Linux等其他操作系统一概不支持。也就是说微软自己造的这些函数不能跨平台使用。
类似的问题还有:以下C语言程序是没有语法错误的
#include <stdio.h>
int main (void) {
int n;
scanf ("%d", &n);
int a[n];
for (int i = 0; i < n; i++) {
scanf ("%d", a + n - 1 - i);
}
for (int i = 0; i < n; i++) {
printf ("%d", a[i]);
putchar ((i < n - 1) ? ' ' : '\n');
}
return 0;
}
然而在MSVC中,这段程序在编译时会产生“表达式必须含有常量值”的编译错误。这是因为C++不支持VLA,MSVC在编译C程序时会拒绝这种与C++标准不一致的C语言特性。
综上,编译C语言程序时不要使用MSVC,可以使用MinGW GCC或LLVM Clang等编译器。新版的VS可以在VS安装程序内安装Clang编译器。