这是受到这个问题以及对一个特定答案的评论的启发,我strncpy在C 中学到了这不是一个非常安全的字符串处理函数,它会填充零,直到它到达n,我不知道的东西.
具体来说,引用R ..
strncpy不会为null终止,并且会对目标缓冲区的其余部分进行空填充,这是一个巨大的浪费时间.您可以通过添加自己的空填充来解决前者,但不能添加后者.它从未打算用作"安全字符串处理"功能,但是用于处理Unix目录表和数据库文件中的固定大小字段.snprintf(dest,n,"%s",src)是标准C中唯一正确的"安全strcpy",但它可能会慢很多.顺便说一下,截断本身可能是一个主要的错误,并且在某些情况下可能会导致权限提升或DoS,因此抛出"安全"字符串函数会在问题中截断其输出并不是使其"安全"或"安全".相反,您应该确保目标缓冲区的大小合适,并且只需使用strcpy(或者更好的是,如果您已经知道源字符串长度,则使用memcpy).
请注意,strncat()在其接口中比strncpy()更令人困惑 - 这个长度参数到底又是什么?根据你提供的strncpy()等,它不是你所期望的 - 所以它甚至比strncpy()更容易出错.为了复制字符串,我越来越认为有一个强烈的论据,你只需要memmove(),因为你总是提前知道所有的大小,并确保提前有足够的空间.使用memmove()优先于strcpy(),strcat(),strncpy(),strncat(),memcpy()中的任何一个.
所以,我在C标准库上显然有些生疏.因此,我想提出一个问题:
哪些C标准库函数使用不当/可能导致/导致安全问题/代码缺陷/效率低下?
为了客观性,我有一些答案的标准:
请避免:
由于这可能被认为是主观的,并且没有明确的答案,我正在为社区维基立刻做好准备.
我也按照C99工作.
当允许使用的唯一浮点指令是387个时,几乎不可能(*)以合理的成本提供严格的IEEE 754语义.当希望保持FPU在完整的64位有效数字上工作时,这一点特别困难,因此该long double类型可用于扩展精度.通常的"解决方案"是以唯一可用的精度进行中间计算,并在或多或少明确定义的场合转换为较低的精度.
根据Joseph S. Myers在2008年GCC邮件列表中发布的解释,GCC的最新版本处理中间计算中的过多精度.gcc -std=c99 -mno-sse2 -mfpmath=387据我所知,这个描述使程序编译完全可预测,到最后一点.如果它偶然没有,那就是一个错误而且它将被修复:约瑟夫S.迈尔斯在他的帖子中声明的意图是使其可预测.
是否记录了Clang如何处理超额精度(比如何时使用该选项-mno-sse2),以及在哪里?
(*)编辑:这是夸大其词.当允许将x87 FPU配置为使用53位有效数字时,这有点令人讨厌,但并不难以模拟binary64.
在下面的R ..评论之后,这里是我与Clang的最新版本之间的短暂互动的日志:
Hexa:~ $ clang -v
Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin12.4.0
Thread model: posix
Hexa:~ $ cat fem.c
#include <stdio.h>
#include <math.h>
#include <float.h>
#include <fenv.h>
double x;
double y = 2.0;
double z = 1.0;
int main(){
x = y + z;
printf("%d\n", (int) FLT_EVAL_METHOD);
}
Hexa:~ $ clang …Run Code Online (Sandbox Code Playgroud) 当我要求查看cc的当前版本时,我得到了这个.
$ cc --version
cc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$
Run Code Online (Sandbox Code Playgroud)
我想知道的是使用c89,c90,c99或c11中的哪一个.
如何使用GCC打印ff long long int和unsigned long long intC99?
我搜索了其他建议使用的帖子,%lld但它给出了这些警告:
警告#1:格式为[-Wformat] |的未知转换类型字符'l'
警告#2:格式参数太多[-Wformat-extra-args] |
对于以下尝试:
#include <stdio.h>
int main()
{
long long int x = 0;
unsigned long long int y = 0;
printf("%lld\n", x);
printf("%llu\n", y);
}
Run Code Online (Sandbox Code Playgroud) 这里是我所遇到的非常简化的问题代码:
enum node_type {
t_int, t_double
};
struct int_node {
int value;
};
struct double_node {
double value;
};
struct node {
enum node_type type;
union {
struct int_node int_n;
struct double_node double_n;
};
};
int main(void) {
struct int_node i;
i.value = 10;
struct node n;
n.type = t_int;
n.int_n = i;
return 0;
}
我不明白的是:
$ cc us.c $ cc -std=c99 us.c us.c:18:4: warning: declaration does not declare anything us.c: In function ‘main’: us.c:26:4: error: ‘struct node’ …
我最近发现存在标准的最快类型,主要是int_fast32_t和int_fast64_t.
我总是被告知,对于主流架构的正常使用,应该更好地使用经典的int和long,它应该总是适合处理器的默认读取容量,因此避免无用的数字转换.
在C99标准中,它在§7.18.1.3p2中说:
"typedef名称int_fastN_t指定宽度至少为N的最快有符号整数类型.typedef名称uint_fastN_t指定宽度至少为N的最快无符号整数类型."
在§7.18.1.3p1中也引用了它:
"对于所有目的,指定的类型不能保证最快;如果实现没有明确的理由选择一种类型而不是另一种类型,它将简单地选择一些满足签名和宽度要求的整数类型."
我不清楚最快的真正含义.我不明白何时应该使用这种类型,何时不应该使用.
我用Google搜索上这一点了,发现了一些开放 源码 项目已经改变了他们的一些功能,但不是所有的人.他们并没有真正解释为什么他们改变了代码的一部分,而只改变了代码的一部分.
当int_fastXX_t 真的比经典的更快时,你知道具体的案例/用法是什么吗?
假设您使用的是支持C99(甚至只是stdint.h)的编译器,是否有任何理由不使用固定宽度整数类型,如uint8_t?
我所知道的一个原因是,char在处理字符而不是使用s时使用s 更有意义(u)int8_t,如本问题所述.
但是如果你打算存储一个数字,你何时想要使用一种你不知道它有多大的类型?即在什么情况下你想要在unsigned short不知道它是8,16甚至32位的情况下存储一个数字,而不是使用uint16t?
接下来,使用固定宽度整数或使用普通整数类型并且从不假设任何东西并且使用sizeof它们需要知道它们使用了多少字节时,它被认为是更好的做法吗?
为了真正符合标准,C中的所有函数(main除外)都必须有原型,即使它们只是在同一个翻译单元中定义之后才使用它们吗?
如果在C中有字符串,则可以在其中添加直接十六进制代码.
char str[] = "abcde"; // 'a', 'b', 'c', 'd', 'e', 0x00
char str2[] = "abc\x12\x34"; // 'a', 'b', 'c', 0x12, 0x34, 0x00
Run Code Online (Sandbox Code Playgroud)
两个示例在内存中都有6个字节.现在,如果要[a-fA-F0-9]在十六进制输入后添加值,则存在问题.
//I want: 'a', 'b', 'c', 0x12, 'e', 0x00
//Error, hex is too big because last e is treated as part of hex thus becoming 0x12e
char problem[] = "abc\x12e";
Run Code Online (Sandbox Code Playgroud)
可能的解决方案是在定义后替换.
//This will work, bad idea
char solution[6] = "abcde";
solution[3] = 0x12;
Run Code Online (Sandbox Code Playgroud)
这可以工作,但如果你把它作为,它将失败const.
//This will not work
const char solution[6] = "abcde"; …Run Code Online (Sandbox Code Playgroud) 今天编译器支持的C99标准有多普遍?据我所知,即使GCC完全支持它.这是正确的吗?
C99的哪些功能比其他功能更受支持,即我可以使用哪些功能来确定大多数编译器都能理解我?