是strtol,strtod不安全吗?

use*_*008 15 c const const-char std c-strings

似乎strtol()并且strtod()有效地允许(并强制)你在字符串中抛弃constness:

#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;
}
Run Code Online (Sandbox Code Playgroud)

上面,我自己没有演出.然而,strtol()基本上把我const char *变成了一个char *对我来说,没有任何警告或任何东西.(事实上,它不会让你输入barconst char *,所以迫使类型的不安全的变化.)是不是真的很危险?

Ada*_*eld 14

我猜这是因为替代方案更糟糕.假设原型已更改为添加const:

long int strtol(const char *nptr, const char **endptr, int base);
Run Code Online (Sandbox Code Playgroud)

现在,假设我们要解析一个非常量字符串:

char str[] = "12345xyz";  // non-const
char *endptr;
lont result = strtol(str, &endptr, 10);
*endptr = '_';
printf("%s\n", str);  // expected output: 12345_yz
Run Code Online (Sandbox Code Playgroud)

但是当我们尝试编译这段代码时会发生什么?编译错误!这是非直观的,但你不能隐含地将a转换char **为a const char **.有关原因的详细说明,请参阅C++ FAQ Lite.它在技术上谈论C++有,但是论据同样适用于C.在C/C++,你只允许隐式转换从"指针类型 "为"指针const 类型 "的最高境界:转换即可执行是从char **char * const *,或等同地从"指针(指针char)"到"指针(const指针char)".

因为我猜想解析一个非常量字符串比解析一个常量字符串更有可能,我会继续假设 - 不const正确的情况下的不正确性比使常见情况成为编译器错误更可取.

  • 但是C++并没有阻止你重载函数:你可以使用`long int strtol(char*nptr,char**endptr,int base);`*和*`long int strtol(const char*nptr,const char**endptr,int base);`:这会修复你的编译错误.实际上,标准对其他类似函数执行此操作,例如`strchr`和`strstr`, (5认同)

Ste*_*sop 7

是的,其他函数具有相同的"常量清洗"问题(例如strchr,strstr,所有那些).

正是由于这个原因,C++增加了重载(21.4:4):函数签名strchr(const char*, int)被两个声明所取代:

const char* strchr(const char* s, int c);
      char* strchr(      char* s, int c);
Run Code Online (Sandbox Code Playgroud)

但是当然在C语言中你不能同时拥有两个具有相同名称的const-correct版本,所以你得到了const-incorrect的妥协.

C++没有提到strtol和strtod的类似重载,实际上我的编译器(GCC)没有它们.我不知道为什么不:你不能隐式char**转换const char**(连同没有重载)的事实解释了C,但我不太清楚C++重载会出现什么问题:

long strtol(const char*, const char**, int);
Run Code Online (Sandbox Code Playgroud)

  • stlport提供了这个重载(和其他一些). (2认同)