函数声明中的参数常量限定符

20

我在头文件中有以下函数声明:

extern void flash(const char *message, const enum msg_type type);

基本上,它需要两个参数,并将相应的消息推入全局消息队列。 由于它不需要修改参数,因此我对它们进行了const限定。 然而,CLion的静态代码分析器发出了警告:

  

Clang-Tidy:函数声明中的参数“type”具有const修饰符; 参数的const限定只对函数定义产生影响。

enter image description here

这是我的问题:

  1. 我都加了const限定符,为什么只有后者会触发警告?
  2. 这真的很糟糕吗? 我知道它没有影响,但从技术角度讲,const限定符也没有影响。
  3. 我能摆脱这个警告吗?

4
你没有对第一个参数加上const限定词。你在指针类型后面加上了 const - M.M
@M.M 你说得对。实际上我在说明第一个参数所指向的内容。 - nalzok
2个回答

23

第一个参数的类型是const char *,或者说是指向常量字符的指针。这意味着您可以将指向不能修改的字符串的指针传递给函数,例如:

const char* msg = "Hello, world!";
flash(msg, SOME_MESSAGE_TYPE);

你不能改变指向const char的指针msg中的字符。将其传递给参数类型为char*的函数将表明该函数可能会更改它们,这是不合法的。参数类型中的这个const与调用者有关,因此保留。

另一方面,enum msg_type只是一个enum,将被复制到函数中。调用函数时,我不关心函数体中发生了什么,type不会影响函数外部的任何内容。说thisconst没有任何区别,因此会出现警告。

如果将第一个参数改为const char *const message,那么也会发出警告。这将表明您无法更改指针message所指向的内容,但调用者并不关心,因为无论它传递的指针如何,都不会更改。


这并不是真正的问题;它只是在告诉你可能会产生混淆,但在这种情况下并没有造成任何损害。但是,您仍然应该消除警告,因为警告表示潜在的问题,并且使用非问题的噪音使您不太可能阅读重要的警告。


更改头文件,但不是在实现flash的任何地方,以便第二个参数上没有const。在实现中保留const,这样就不会在函数体内实际更改type,但在声明中不需要它。


1
+1 不知道函数定义(指定内部实现)和声明(指定外部接口)之间的微妙差别。 - nalzok
1
@chux 我知道我应该再检查一遍。我主要使用C++,并且知道细节上存在差异,但是当我说这个时,我认为我在坚持某些安全的东西(至少按照C11标准)。由于这涉及类型系统而不是UB,因此我重新设计了示例,以不直接使用字符串字面量。 - Daniel H
1
常量值在声明中不会影响函数的签名,因此不应该放在函数声明中。为了最佳实践,该值应通过引用传递。 - Arun Kumar
那为什么确切地是这样,@DanielH?仅仅是因为对呼叫者没有影响吗? - user129393192
大约是这样的。如果 const 只在函数体内部改变事物,那么它对调用函数的方式没有任何影响。调用者不知道也不关心。 - Daniel H
显示剩余9条评论

3
我将两个参数都使用了const限定符,为什么只有后者触发了警告?
正如您的警告所说,它不会影响原型,只会影响实现。
这真的很糟糕吗?
就是噪声,因为它并不影响任何东西,但除此之外,没有问题。
我可以摆脱这个警告吗?
您可以安全地删除常量限定符,因为它不需要。
然而,通常使用clang-tidy抑制警告似乎有点混乱。这个链接可能会有所帮助: clang-tidy:如何抑制警告? 但是这些警告实际上可能是一种福音。意外地写成int foo(const char *)而不是int foo(char * const)并不罕见。后者不会触发此警告,因此如果您收到此警告,则表示您已经混淆了某些内容。

如果我的意图是不修改字符,那么说“const char *”有什么问题吗? - user129393192
如果我的意图是字符不会被修改,那么说const char *有什么问题吗? - undefined
@user129393192 那没有任何问题 - klutt
@user129393192 那没有任何问题 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接