C strtol、strtod是否不安全?
似乎C strtol、strtod是否不安全?,c,constants,std,c-strings,const-char,C,Constants,Std,C Strings,Const Char,似乎strtol()和strtod()有效地允许(并强制)您丢弃字符串中的常量: #include <stdlib.h> #include <stdio.h> int main() { const char *foo = "Hello, world!"; char *bar; strtol(foo, &bar, 10); // or strtod(foo, &bar); printf("%d\n", foo == bar); // pri
strtol()
和strtod()
有效地允许(并强制)您丢弃字符串中的常量:
#include <stdlib.h>
#include <stdio.h>
int main() {
const char *foo = "Hello, world!";
char *bar;
strtol(foo, &bar, 10); // or strtod(foo, &bar);
printf("%d\n", foo == bar); // prints "1"! they're equal
*bar = 'X'; // segmentation fault
return 0;
}
#包括
#包括
int main(){
const char*foo=“你好,世界!”;
字符*条;
strtol(foo,&bar,10);//或strtod(foo,&bar);
printf(“%d\n”,foo==bar);//打印“1”!它们相等
*bar='X';//分段错误
返回0;
}
如上所述,我自己没有进行任何石膏。但是,
strtol()
基本上是将我的const char*
转换成一个char*
,没有任何警告或任何东西。(事实上,它不允许您将bar
作为const char*
,从而强制进行不安全的类型更改。)这不是很危险吗?第一个参数的“const char*”意味着strtol()
不会修改字符串
如何处理返回的指针是您的事情
是的,它可以被视为一种类型的安全违规行为;C++可能会做不同的事情(尽管,据我所知,ISO/IEC 1488—1998定义了<代码> <代码>和C相同的签名)。 < P>我猜,因为替代方案更糟。假设原型更改为添加
常量
:
long int strtol(const char *nptr, const char **endptr, int base);
现在,假设我们要分析一个非常量字符串:
char str[] = "12345xyz"; // non-const
char *endptr;
lont result = strtol(str, &endptr, 10);
*endptr = '_';
printf("%s\n", str); // expected output: 12345_yz
但是当我们试图编译这段代码时会发生什么呢?编译器错误!这相当不直观,但您不能隐式地将char**
转换为const char**
。有关原因的详细说明,请参见。从技术上讲,C++中的参数是一样的,但是对于C/C++中的C.来说,这些参数同样有效,您只允许在最高级别上从“指针到类型”到“指针到代码> const < /C>类型”隐式转换:您可以执行的转换是从代码> char **/COD> > <代码> char * const */COD>,或者等价于“指针”。(指向char
)“指向(const
指向char
)”的指针
因为我猜想解析一个非常量字符串比解析一个常量字符串更有可能,所以我会继续假设
const
-对于不太可能的情况来说,不正确性比将普通情况作为编译器错误要好。是的,其他函数也有同样的“const”问题(例如,strchr、strstr,所有这些)
由于C++的原因,C++增加了重载(21.4:4):函数签名<代码> Schchr(const char,int)< /c>被两个声明替换:
const char* strchr(const char* s, int c);
char* strchr( char* s, int c);
当然,在C语言中,不能同时使用相同名称的两个const-correct版本,因此会得到const-correct版本
C++没有提到strtol和strtod的类似重载,事实上我的编译器(GCC)也没有。我不知道为什么没有:你不能隐式地将char**
转换为const char**
(加上没有重载)解释C,但我不太清楚C++过载的错误:
long strtol(const char*, const char**, int);
我有一个编译器,在C++模式下编译时:
extern "C" {
long int strtol(const char *nptr, const char **endptr, int base);
long int strtol(char *nptr, char **endptr, int base);
}
显然,这两者都解析为相同的链接时间符号
<>编辑:根据C++标准,这个头不应该编译。我猜编译器根本没有检查这个。实际上,定义在系统头文件中出现。 C++定义了Sttol(以及在CSTDLIB中的所有其他内容)。与C相同,但不是cStand和CWCHAR中的所有签名。但是C++并不能阻止您重载函数:您可以有<代码> long int Strut(char *nptR,char **EntpR,int基);< /C>和<代码> long int Strut(const char *nptR,const char **EntpR,int基)实际上,标准是这样做的,对于其他这样的函数,比如<代码> Strucr 和