有很多关于这个特定警告的帖子,但我找不到专门引用像 strtod
和 friend 那样的函数签名的帖子。
我有一个函数 int foo(const char *str, char **end)
,我发现之前没有办法设置 *end = str
返回整数而不会遇到上述警告。是否有一些我遗漏的附加限定符,或者我将不得不“忍受”的东西?
最佳答案
如果我没记错的话,这实际上是现代 C 标准中的一个大胖子。没有显式转换就不可能实现 strtod
。过去有大量关于此的讨论,并提出了对该语言进行奇怪扩展的激进提议,以便可以“正确地”编写 strtod
。但治法都比治病更糟,所以最终激进的提议没有被采纳,结果是写strtod
之类的东西很棘手(但并非不可能)。
在您的实现中,您通常会有一个指针 p
指向您没有解析的第一个字符。由于 p
的初始值是您的输入字符串,即 const char *
,您的 p
通常是 const char *
,也是。 (这很好,因为您不打算在解析字符串时使用 p
来修改它。)但是当需要设置 endp
时,您您只需使用强制转换即可:
*endp = (char *)p;
像这样“抛弃常量”感觉很糟糕,但它确实是唯一的方法,而且实际上完全合法,正如 Eric P. 在 another answer here 中解释的那样。
(另一种可能性是 *(const char **)endp = p;
,但它的输入更多,甚至看起来更粗略,结果证明它并不严格合法。)
通常规则是像这样的显式转换是糟糕的形式。通常建议是找到一种不需要显式转换的方法。虽然一般规则是好的,但这是一个异常(exception),纯粹而简单。基于正在发生的所有其他事情,结论是您需要此类型转换,如果您尝试在没有它的情况下过关,您最终不得不在其他地方做更糟糕的事情。
在回答评论中的一个问题时,我们不能让 endp
成为 const char **
的原因是它给调用者带来了不便.调用者可能正在使用非 const
限定的指针。现在,如果调用者有
char *str = "123.456xyz";
然后调用
double d = strtod(str, NULL);
这很好:可以将常规 char *
传递给需要 const char *
的函数。但是如果调用者想要取回结束指针,并且额外声明
char *endp;
然后调用
double d = strtod(str, &endp);
如果 strtod
声明为
double strtod(const char *, const char **);
事实证明这是行不通的。您可以将 char *
传递给需要 const char *
的函数,但您可以不传递 char **
到需要 const char **
的函数。为什么你不能的解释相当模糊。 C FAQ list 中有某种连贯的解释。
关于c - 如何在不收到警告 `strtod` char "Assigning to ' const char *' from ' 的情况下复制 *' discards qualifier"等的功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68340938/
我在提交更改时不小心单击了放弃。所以我丢弃了整个文件,但我只想丢弃一些大块头。但是我没有点击提交,我没有点击取消。 但是现在我在我的文件中看不到我的代码。 我该怎么做才能撤消该死的丢弃? 提前致谢 最
我们有一个变更集,开发人员已在其中 checkin 了对源分支和目标分支的更改,许多更改包括两个分支中的重命名。从源分支到目标分支的变更集合并正常,但变更集仍保留在要合并的变更集列表中。 当我现在尝试
设置: 我有一个表单和一个“提交”按钮。理想情况下,用户应该填写表格,单击“提交”,然后离开选项卡。如果他尝试离开选项卡而不保存更改,我需要通过 3 个选项提醒他: 保存 放弃:放弃表单数据更改,并保
从 C# 7 开始,我们可以使用丢弃 _ 来丢弃未使用的变量。我用它做的事情之一是即发即弃任务。 考虑这个方法: public Task Example() { // Do some fire
昨晚不经意间做了一件很蠢的事。我已经在 iPad 项目上工作了几个月并且(甚至更愚蠢)没有备份。通过在 XCODE 中右键单击该项目,我错误地单击了“放弃更改” (愚蠢再次占据上风)自最初以来我没有任
我有一个修改和实例化的 Action ,然后链接到另一个 Action 。如果实例上有错误,我想忽略所做的更改。但是,throws()方法不起作用。状态更改始终保持不变。我究竟做错了什么? def r
我刚刚意识到 GL_ALPHA_TEST自 OpenGL 3.0 起已被弃用,因此我无法将它与 glEnable() 一起使用。我已经尝试快速搜索谷歌现在如何替换它(以及为什么它被弃用),但未能找到这
使用 CPP map ,从 eclipse 编辑器获取警告信息。 Point find_shortest_node(const vector &openset,const map &f_score
我不理解以下示例中 x3 的行为(取自更大的语法)。 当然,语法有点奇怪,但大致实现了 (lal)?()? .当第二组不存在时,默认为 .我不明白为什么要输入 "lal"我得到 defaultcha
这个问题在这里已经有了答案: Is there a way to make bash job control quiet? (5 个答案) 关闭 3 年前。 我正在运行这个命令: nohup goo
当我尝试在 LWJGL 3 中实现纹理的透明度时,模型似乎以完全透明的方式渲染,因此根本不可见。当我删除支票时,它工作正常。有什么线索可以解释为什么吗? 下面是检查 alpha 分量的着色器代码: #
使用 GCC 和 C99 模式,我有一个函数声明为: void func(float *X); 当我调用该函数时,我使用了一个可变数组 Y: volatile float Y[2]; int main
本文整理了Java中org.jruby.parser.YYDebug.discard()方法的一些代码示例,展示了YYDebug.discard()的具体用法。这些代码示例主要来源于Github/St
可以使用加号按钮“暂存此行”轻松暂存行。 有“Discard Hunk”和“Stage Hunk”符号。 但是如何“丢弃行”呢?有什么快捷方式可以将行旁边的加号按钮更改为减号按钮吗? 最佳答案 您可以
我已经使用 jQuery.ajax() 方法构建了实时搜索。在每个 keyup 事件中,它都会从服务器接收新的结果数据。 问题是,当我打字速度非常快时,例如“foobar”和“fooba”的GET请求
我有一个看起来像这样的图形日志: (snip) | | | o 1) Other Dev: Commit | | \ o | | 2) Me: Commit / | | | |
我只是想将 mesos 版本从 1.0.3 升级到 1.3.1。 Chronos 调度程序能够通过 mesos 调度 JOB。该作业运行良好并且能够看到 mesos stdout 日志。但是,仍然在
我有一个要调试的 BufferedInputStream。为此,我使用此方法(Log.d 和 Log.wtf 只是 Android 特定的日志记录工具,除此之外其行为不应与纯 Java 不同):
假设它是使用“放弃 merge 中的所有更改...”选项执行 merge 的,但意外。 这个错误的提交已经提交到“中央”存储库中。 如果我遇到这种情况如何处理需要以正确的方式 merge 分支的变化?
我尝试将数据从 Firebase 数据库检索到我的回收站 View ,无论我尝试什么,我都会收到此错误。我该如何解决这个问题? 在我的模拟器中,Google Play 服务版本是:11.5.80 我没
我是一名优秀的程序员,十分优秀!