19

I have the following function declaration in a header file:

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

Basically, it takes two parameters and pushes a corresponding message into a global message queue. Since it doesn't need to modify the parameters, I const-qualified them. However, CLion's static code analyzer emitted a warning about it:

Clang-Tidy: Parameter 'type' is const-qualified in the function declaration; const-qualification of parameters only has an effect on function definitions

enter image description here

Here is my questions:

  1. I const-qualified both parameters, why does only the latter trigger a warning?
  2. Is it really bad? I know it has no effect, but technically specking const qualifiers have no effect too.
  3. Can I get rid of this warning?
walrus
  • 171
  • 2
  • 11
nalzok
  • 14,965
  • 21
  • 72
  • 139

2 Answers2

22

The first parameter is of type const char *, or pointer to constant character. This means that you can pass into the function a pointer to a string which you can't modify, for example:

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

You can't change the characters in msg; it's a pointer to const char. Passing it to a function with parameter type char* would indicate the function might change them, which would be illegal. This const in the parameter type is relevant to the caller, so is kept.

On the other hand, enum msg_type is just an enum, and will be copied into the function. When calling the function, I don't care what happens in the body of the function with type; it won't affect anything outside the function. Saying that this is const doesn't make a difference, hence the warning.

If you change the first parameter to const char *const message, then it'll warn about that too. That would indicate that you can't change what the pointer message points to, which again the caller doesn't care about because whatever pointer it passes in won't change.


This isn't really bad; it's telling you that you might be confused, but in this case it doesn't hurt anything. You should still get rid of the warning, though, because warnings indicate potential problems and clogging them with non-problematic noise just makes it less likely you'll read the important ones.


Change the header file, but not wherever flash is implemented, to not have const on the second parameter. Where it's implemented, keep the const so you don't actually change type inside the function body, but it's not needed in the declaration.

Daniel H
  • 7,223
  • 2
  • 26
  • 41
  • 1
    +1 didn't know this subtle difference between function definition (which specifies the internal implementation) and declaration (which specifies the external interface) – nalzok Jul 16 '18 at 02:44
  • 1
    @chux I knew I should have double-checked. I primarily use C++ and knew there were differences in the details, but I *thought* I was sticking to something safe (at least by C11) when I said that. Since this is about the type system and not UB, I reworked the example to not use a string literal directly. – Daniel H Jul 16 '18 at 04:09
  • 1
    const values in declarations do not affect the signature of a function, so you should not be put in the function declaration. For best practice, the value should pass by reference. – Arun Kumar Jun 27 '19 at 12:53
  • @Arun The question is tagged C, not C++; C doesn't have references. Even if it did, `msg` is already a pointer and it's probably better performance to pass an `enum` by value. – Daniel H Jun 28 '19 at 18:28
  • Seems odd to me that we are supposed to make the declaration not match the implementation, but there's a lot of weird stuff in C/C++ so I guess I just call it "idiomatic style" and roll with it. – Code Abominator Dec 22 '20 at 03:38
  • So should header files not have something like `const char *` as a paremeter? – user129393192 Jun 22 '23 at 19:21
  • @user129393192 That would be a pointer to constant character; the header file should specify that. Only the “outer-most” `const` (the one that would apply to the pointer, not the pointed-to `char`s) is irrelevant in the header file. – Daniel H Jun 22 '23 at 20:16
  • And why exactly is that @DanielH? Is it simply because it makes no difference to the caller? – user129393192 Jun 22 '23 at 20:16
  • @user129393192 Approximately, yes. If the `const` only changes things within the body of the function, then it changes nothing about how calling the function works. The caller doesnʼt know or care. – Daniel H Jun 23 '23 at 01:48
  • Got it, and that is b/c the callee can mutate the value, and the caller will never see it. @DanielH – user129393192 Jun 23 '23 at 03:15
3

I const-qualified both parameter, why does only the latter trigger a warning?

As your warning says, it does not affect a prototype. It only affects the implementation.

Is it really bad?

It is noise in the meaning that it does not affect anything, but other than that, no.

Can I get rid of this warning?

You can safely remove the const qualifier since it is not needed.

However, it seems a bit messy to suppress warnings in general with clang-tidy. This link might help:

clang-tidy: How to suppress warnings?

But these warnings can actually be a blessing. It's not very uncommon to accidentally write int foo(const char *) instead of int foo(char * const). The latter would not trigger this warning, so if you get this warning it's a sign that you have mixed something up.

klutt
  • 30,332
  • 17
  • 55
  • 95