Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C strtol、strtod是否不安全?_C_Constants_Std_C Strings_Const Char - Fatal编程技术网

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 和 STRSTR> /Cord>,可以引用C FAQ网站,更具体地,而不是C++ FAQ,虽然我不完全相信这些解释很容易理解。(和其他一些人)。