c - 使用 c11 标准和 clang 来使用 strcpy_s
问题描述
我正在运行 OS X Sierra 并尝试编译使用 ac 的程序strcpy_s
,但我安装的 clang 编译器使用的是 c99 标准,但从我所读到的 strcpy_s 需要 c11。
这是我要编译的代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char source[] = "Test string";
char destination[50];
if(strcpy_s(destination, sizeof(destination), source))
printf("string copied - %s",destination);
return 0;
}
这是我用来编译的命令
$ clang copytest.c -o copytest
copytest.c:11:5: warning: implicit declaration of function 'strcpy_s' is invalid in C99 [-Wimplicit-function-declaration]
if(strcpy_s(copied_string, sizeof(copied_string), source))
^
1 warning generated.
Undefined symbols for architecture x86_64:
"_strcpy_s", referenced from:
_main in copytest-e1e05a.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
我试过用标准标志编译......
clang -std=c11 copytest.c -o copytest
但我得到了相同的“在 c99 中无效”警告。我也尝试过使用 gcc 进行编译,但仍然收到相同的 c99 警告。
我尝试通过自制软件进行升级,显示如下
警告:gcc 9.2.0 已经安装并且是最新的
我有 clang 版本 9.0.0
$ clang -v
Apple LLVM version 9.0.0 (clang-900.0.39.2)
我的 xcode 版本是 Xcode 9.2,从我读过的所有内容来看,它应该带有 c11 支持。
我在编译时做错了什么,我的代码本身不正确吗?这是我在这里找到的唯一类似的问题,但它甚至没有答案。谢谢
解决方案
这些_s
函数是2011 C 标准(附件 K )的可选组件,据我所知,它们从未作为任何 C 库的集成部分实现。可移植代码不能依赖于它们的可用性。(用于 Windows 的 Microsoft 的 C 编译器实现了一组重叠的函数,它们具有相同的名称但不同的语义(有时甚至是不同的参数列表),并且至少存在一个附加实现。 请参阅这个旧答案,以及更长的问题并回答它的链接,以获取更多详细信息。)
此外,这些_s
函数并没有解决它们打算解决的问题(不安全的字符串处理);有必要对 的每次使用进行适当的修复strcpy
,而不是像附件 K 的作者所希望的那样全局搜索和替换strcpy
等strcpy_s
。如果您确实在一个正确的修复,您将不需要任何_s
功能来实现它。例如,这是您的示例程序的固定版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char source[] = "Test string";
char destination[50];
size_t srclen = strlen(source);
if (srclen + 1 > sizeof destination) {
fprintf(stderr, "string too long to copy - %zu bytes, need %zu\n",
sizeof destination, srclen + 1);
return 1;
} else {
memcpy(destination, source, srclen + 1);
printf("string copied - %s\n", destination);
return 0;
}
}
这是一个更好的版本:
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "usage: ./test 'message of arbitrary length'\n");
return 1;
}
char *destination = strdup(argv[1]);
if (!destination) {
perror("strdup");
return 1;
}
printf("string copied - '%s'\n", destination);
free(destination);
return 0;
}
因此:切勿使用任何_s
功能。如果您需要编写一个在 Windows 上编译且没有警告的程序,请将其放在#define _CRT_SECURE_NO_WARNINGS 1
每个文件的顶部,以使 MSVC 停止给您错误的建议。
推荐阅读
- c# - 单元测试中的配置值永远不会被设置
- c# - MySQL、C# 和 C# 之间的字符编码
- android - 更新gradle后将多模块项目发布到工件停止工作
- css - 如何在 reacttjs 中修复 video.js 包的 css
- swift - 数据请求为零,处理来自 REST API 的请求时出现问题
- react-admin - 如何在 ArrayImput 和 SimpleFormIterator 中对输入进行水平排序
- macros - Elixir:defmacro 和 pipline 的基准测试
- java - 如果我使用 getText() 方法,有什么方法可以只获取 json 数据
- html - 获取@Html.DropDownList 或选择值
- git - 将最新提交压缩到最后一次合并提交