319

I have a cross platform application and in a few of my functions not all the values passed to functions are utilised. Hence I get a warning from GCC telling me that there are unused variables.

What would be the best way of coding around the warning?

An #ifdef around the function?

#ifdef _MSC_VER
void ProcessOps::sendToExternalApp(QString sAppName, QString sImagePath, qreal qrLeft, qreal qrTop, qreal qrWidth, qreal qrHeight)
#else
void ProcessOps::sendToExternalApp(QString sAppName, QString sImagePath, qreal /*qrLeft*/, qreal /*qrTop*/, qreal /*qrWidth*/, qreal /*qrHeight*/)
#endif
{

This is so ugly but seems like the way the compiler would prefer.

Or do I assign zero to the variable at the end of the function? (which I hate because it's altering something in the program flow to silence a compiler warning).

Is there a correct way?

Jim Fell
  • 13,750
  • 36
  • 127
  • 202
Phil Hannent
  • 12,047
  • 17
  • 71
  • 118
  • 7
    I just realized you asked a similar question last November. This is why it looks familiar! ;) http://stackoverflow.com/questions/308277/what-is-the-consequences-of-ignoring-warning-unused-parameter/308286 – Alex B Sep 28 '09 at 13:18
  • 9
    Why not just comment them out for both compilers? If the arg is unused on one, it'll probably be unused on the other... – Roger Lipscombe Sep 28 '09 at 13:28
  • 12
    you should know that Qt has a `Q_UNUSED` macro just for this. Check it out in the documentation. – Evan Teran Sep 28 '09 at 14:04
  • 1
    The C solution works fine in C++ too: http://stackoverflow.com/a/3599170/1904815 – JonnyJD Feb 17 '14 at 13:01
  • -Wno-unused-parameter might also be an option if you can have compiler-specific build flags – Code Abominator Apr 16 '18 at 21:01
  • Core guidelines F9: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-unused – GrendleM Sep 16 '20 at 17:37

23 Answers23

418

You can put it in "(void)var;" expression (does nothing) so that a compiler sees it is used. This is portable between compilers.

E.g.

void foo(int param1, int param2)
{
    (void)param2;
    bar(param1);
}

Or,

#define UNUSED(expr) do { (void)(expr); } while (0)
...

void foo(int param1, int param2)
{
    UNUSED(param2);
    bar(param1);
}
Community
  • 1
  • 1
Alex B
  • 82,554
  • 44
  • 203
  • 280
  • 26
    +1 - still I would document why you don't use the variable even if it's there. – Tobias Langner Sep 29 '09 at 09:41
  • 22
    This is how `Q_UNUSED` is implemented in principle. – Dmitrii Volosnykh Jan 17 '12 at 11:02
  • Hmm, with MSVC2012 I get 'cannot convert from nullptr to void' when using this with `nullptr` (it's a templated library), sigh. – Cameron Oct 07 '13 at 02:14
  • 15
    @Cameron you can simply omit parameter name in C++. If it's templated, it won't be used in C, so you don't need the cast-to-void trick. – Alex B Oct 07 '13 at 04:55
  • @Alex: Yep, normally good advice, but in my case I was actually using the parameter in an initializer list with `std::forward`, and the warning was erroneous! – Cameron Oct 07 '13 at 12:34
  • 16
    Just `#define UNUSED(expr) (void)(expr)` should work too (without the do-while). – JonnyJD Feb 17 '14 at 13:02
  • 8
    I wonder how to do that for a variadic template. In `template void f(const Args&... args)` I can't write `(void)args;` or `(void)args...;` because both are syntax errors. – panzi May 18 '14 at 16:27
  • 2
    WARNING: In optimized builds the void cast will often be optmized away, still resulting in an unused variable error. – AffluentOwl Jul 15 '15 at 20:30
  • 2
    MSVC 2013 will fail with an undefined type error if you cast a reference to an incomplete type to void. E.g. `struct Foo; void bar(Foo & foo) { (void)foo; }` results in an error "Use of undefined type Foo". A workaround is to take foo's address before casting: `(void)&foo`. So `#define UNUSED(arg) ((void)&(arg))` is the most portable, although ugly. – SnakE Jul 22 '15 at 22:27
  • __attribute__((unused)) as pointed out in answer below is the best way to do this – Curious Dec 30 '15 at 13:43
  • One value case of seeming not used variable is to use some value to register or trigger some initialize process. – FaceBro Sep 10 '17 at 15:03
  • I still get a compile time error `variable or field '...' declared void` – puk Apr 10 '18 at 05:14
  • `(void)param2;` silences my compilers [-Wunused-variable] warning but so does `param2 = param2;` – Robert Schindehette Jan 16 '19 at 04:42
  • 1
    @panzi : Use pack expansion, something like: `(void) (0 + ... + (args, 0))` – Mark K Cowan Jan 16 '19 at 19:38
  • 3
    @MarkKCowan Or just `((void)args, ...)`. – L. F. Jul 08 '19 at 11:34
  • This answer is 11 years old and was IMHO right at the time. Since then, we have multiple `cast();` expressions. In this case, the right one is `static_cast(param);`. – Adam Chalcraft Mar 31 '20 at 19:52
  • IMO @kreuzerkrieg answer is actually the correct answer – GrendleM Sep 16 '20 at 17:34
136

In GCC and Clang you can use the __attribute__((unused)) preprocessor directive to achieve your goal.
For example:

int foo (__attribute__((unused)) int bar) {
   return 0;
}
ezpz
  • 11,767
  • 6
  • 38
  • 39
127

C++17 now provides the [[maybe_unused]] attribute.

http://en.cppreference.com/w/cpp/language/attributes

Quite nice and standard.

scx
  • 3,221
  • 1
  • 19
  • 37
  • 1
    This would be the best answer, unfortunately this solution seems to trigger some warnings in gcc https://stackoverflow.com/questions/50646334/maybe-unused-on-member-variable-gcc-warns-incorrectly-that-attribute-is – Antonio Jan 05 '21 at 12:45
  • Works fine for me with gcc, you probably just need to enable c++17 or c++20 – Adrian Maire May 25 '22 at 16:27
56

C++17 Update

In C++17 we gain the attribute [[maybe_unused]] which is covered in [dcl.attr.unused]

The attribute-token maybe_unused indicates that a name or entity is possibly intentionally unused. It shall appear at most once in each attribute-list and no attribute-argument-clause shall be present. ...

Example:

 [[maybe_unused]] void f([[maybe_unused]] bool thing1,
                        [[maybe_unused]] bool thing2) {
  [[maybe_unused]] bool b = thing1 && thing2;
    assert(b);
 }

Implementations should not warn that b is unused, whether or not NDEBUG is defined. —end example ]

For the following example:

int foo ( int bar) {
    bool unused_bool ;
    return 0;
}

Both clang and gcc generate a diagnostic using -Wall -Wextra for both bar and unused_bool (See it live).

While adding [[maybe_unused]] silences the diagnostics:

int foo ([[maybe_unused]] int bar) {
    [[maybe_unused]] bool unused_bool ;
    return 0;
}

see it live.

Before C++17

In C++11 an alternative form of the UNUSED macro could be formed using a lambda expression(via Ben Deane) with an capture of the unused variable:

#define UNUSED(x) [&x]{}()

The immediate invocation of the lambda expression should be optimized away, given the following example:

int foo (int bar) {
    UNUSED(bar) ;
    return 0;
}

we can see in godbolt that the call is optimized away:

foo(int):
xorl    %eax, %eax
ret
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • 7
    So you mention C++11 and then manage to present a macro?! Ouch! Maybe using a function would be cleaner? `template inline void NOTUSED( T const & result ) { static_cast(result); }` You could also use a lambda in the function, I suppose. – Alexis Wilke Sep 23 '16 at 00:50
  • godbolt is a great resource – yano Nov 10 '16 at 19:54
  • 9
    `[&x]{}()` does not really silence the warning, but passes the warning over from caller function to the lambda instead. It'll take time till compilers identify this as a warning, but clang-tidy already complains about an unused variable in capture list. – nVxx Apr 17 '18 at 12:06
45

Your current solution is best - comment out the parameter name if you don't use it. That applies to all compilers, so you don't have to use the pre-processor to do it specially for GCC.

alex tingle
  • 6,920
  • 3
  • 25
  • 29
  • 8
    Just to reinforce this answer - you don't need the #ifdef, just comment out the unused parameter names. – quamrana Sep 28 '09 at 14:54
  • 6
    I have a case where the parameter is part of a callback and commenting it out breaks the compile (so I'm not sure why `g++` is warning about it.) In such a case, what would you recommend? – Drew Noakes Jan 31 '13 at 20:36
  • 1
    Imagine an inline virtual method with unused parameters /*commented*/, the client of the interface will not see the parameter name during autocompletion in most IDEs. In this case the UNUSED() solution is more convenient, although less cleaner. – cbuchart Jul 17 '14 at 06:57
  • I think simpler is better, commenting out is very clear – fievel Nov 16 '18 at 10:07
  • @DrewNoakes did you just comment out the parameter name or also the parameter type? – Zac Sep 28 '22 at 15:55
  • @Zac sorry, that was nine years ago. I have no idea. – Drew Noakes Oct 10 '22 at 03:09
29

An even cleaner way is to just comment out variable names:

int main(int /* argc */, char const** /* argv */) {
  return 0;
}
Marcin Wyszynski
  • 2,188
  • 1
  • 17
  • 16
  • 11
    This is not good if you have doxygen and want to document the parameters. – Alexis Wilke Feb 02 '14 at 05:47
  • 23
    @AlexisWilke: That would qualify as a bug in doxygen, IMO – 6502 Apr 10 '14 at 12:30
  • 3
    You can #define YOUR_PROJECT_UNUSED(argname) conditionally upon #ifdef DOXYGEN so that doxygen can see the name and the real compiler does not, via int main(int YOUR_PROJECT_UNUSED(argc), ...). Not fabulous, but does work. – mabraham May 07 '15 at 13:11
  • I find it very painful to comment out a block of code with many such nested comments. (the compiler complains about every one). – Jeff McClintock Jun 14 '18 at 23:12
  • @JeffMcClintock just use single-line comments. Most decent editors support vertical block editing (e.g. [Ctrl]+[V] in Vim). Otherwise, use `#if 0 / #endif` block comments. – Ruslan Aug 13 '18 at 09:46
  • while this fix is common, it fails in `for (auto i : ranges::view::indices(N)) { /* something that doesn't depend on i*/ }`. here one must not comment out `i`. – pseyfert Aug 29 '18 at 09:34
27

doesn't flag these warnings by default. This warning must have been turned on either explicitly by passing -Wunused-parameter to the compiler or implicitly by passing -Wall -Wextra (or possibly some other combination of flags).

Unused parameter warnings can simply be suppressed by passing -Wno-unused-parameter to the compiler, but note that this disabling flag must come after any possible enabling flags for this warning in the compiler command line, so that it can take effect.

Digital Trauma
  • 15,475
  • 3
  • 51
  • 83
  • 2
    Even though, this might not be the best answer to the question (because the question was how to avoid the warning, not how to disable it), this answer might be the people coming from google (like me) were searching for ("how to disable this warning"). So I give +1, thanks for your answer! – mozzbozz Sep 11 '14 at 11:28
25

A coworker just pointed me to this nice little macro here

For ease I'll include the macro below.

#ifdef UNUSED
#elif defined(__GNUC__) 
# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) 
#elif defined(__LCLINT__) 
# define UNUSED(x) /*@unused@*/ x 
#else 
# define UNUSED(x) x 
#endif

void dcc_mon_siginfo_handler(int UNUSED(whatsig))
16

macro-less and portable way to declare one or more parameters as unused:

template <typename... Args> inline void unused(Args&&...) {}

int main(int argc, char* argv[])
{
    unused(argc, argv);
    return 0;
}
Philippe
  • 422
  • 4
  • 7
10

I have seen this instead of the (void)param2 way of silencing the warning:

void foo(int param1, int param2)
{
    std::ignore = param2;
    bar(param1);
}

Looks like this was added in C++11

krupan
  • 3,920
  • 5
  • 27
  • 24
10

Lol! I dont think there is another question on SO that reveal all the heretics corrupted by Chaos better that this one!

With all due respect to C++17 there is a clear guideline in C++ Core Guidelines. AFAIR, back in 2009 this option was available as well as today. And if somebody says it is considered as a bug in Doxygen then there is a bug in Doxygen

kreuzerkrieg
  • 3,009
  • 3
  • 28
  • 59
  • 3
    how typical for SO! the best answer having the lowest voting... (palmface) – Dmitry Jul 07 '20 at 19:57
  • 1
    C++ core guidelines are pretty clear F.9: Unused parameters should be unnamed. I love the note... Note: Allowing parameters to be unnamed was introduced in the early 1980 to address this problem. – GrendleM Sep 16 '20 at 17:30
9

Using preprocessor directives is considered evil most of the time. Ideally you want to avoid them like the Pest. Remember that making the compiler understand your code is easy, allowing other programmers to understand your code is much harder. A few dozen cases like this here and there makes it very hard to read for yourself later or for others right now.

One way might be to put your parameters together into some sort of argument class. You could then use only a subset of the variables (equivalent to your assigning 0 really) or having different specializations of that argument class for each platform. This might however not be worth it, you need to analyze whether it would fit.

If you can read impossible templates, you might find advanced tips in the "Exceptional C++" book. If the people who would read your code could get their skillset to encompass the crazy stuff taught in that book, then you would have beautiful code which can also be easily read. The compiler would also be well aware of what you are doing (instead of hiding everything by preprocessing)

Ben Dadsetan
  • 1,565
  • 11
  • 19
  • 8
    "Using preprocessor directives is considered evil most of the time." Really? By who? – Graeme Perrow Sep 28 '09 at 13:51
  • 15
    By anyone who cares about scope, being able to debug properly, or their sanity. – Bill Sep 28 '09 at 14:22
  • 3
    @Graeme, it looks innocent when we only see 4 lines of it, but spread around it does cause headache. #ifdef basically allows you to put multiple versions of a source code of which the compiler will only see one. As Bill mentions, it also makes it harder to debug. I have read about the evilness of preprocessor directives in diverse books and blogs, as well as having experienced it myself. Of course, everything is relative. Sometimes preprocessor directives simply make sense because anything else would have worse consequences, and my point is here only that it should be avoided where possible. – Ben Dadsetan Sep 28 '09 at 17:44
  • 2
    Overuse is bad, but I would call `#define UNUSED(expr) (void)(expr)` appropriate. – JonnyJD Feb 17 '14 at 13:03
7

First off the warning is generated by the variable definition in the source file not the header file. The header can stay pristine and should, since you might be using something like doxygen to generate the API-documentation.

I will assume that you have completely different implementation in source files. In these cases you can either comment out the offending parameter or just write the parameter.

Example:

func(int a, int b)
{
    b;
    foo(a);
}

This might seem cryptic, so defined a macro like UNUSED. The way MFC did it is:

#ifdef _DEBUG
#define UNUSED(x)
#else
#define UNUSED(x) x
#endif

Like this you see the warning still in debug builds, might be helpful.

rioki
  • 5,988
  • 5
  • 32
  • 55
4

Is it not safe to always comment out parameter names? If it's not you can do something like

#ifdef _MSC_VER
# define P_(n) n
#else
# define P_(n)
#endif

void ProcessOps::sendToExternalApp(
    QString sAppName, QString sImagePath,
    qreal P_(qrLeft), qreal P_(qrTop), qreal P_(qrWidth), qreal P_(qrHeight))

It's a bit less ugly.

Michael Krelin - hacker
  • 138,757
  • 24
  • 193
  • 173
  • 4
    The fact that the param name isn't mandatory in C++ -- it is in C -- is just to give a standard and easy way to prevent the warning. – AProgrammer Sep 28 '09 at 13:24
  • 1
    @hacker, never said it was. I tend to point out differences between C and C++, especially when they are in regions which you'd think is the common subset... Just an habit because I'm working on a mixed code base. – AProgrammer Sep 28 '09 at 15:09
4

Using an UNREFERENCED_PARAMETER(p) could work. I know it is defined in WinNT.h for Windows systems and can easily be defined for gcc as well (if it doesn't already have it).

UNREFERENCED PARAMETER(p) is defined as

#define UNREFERENCED_PARAMETER(P)          (P)

in WinNT.h.

Joshua
  • 8,112
  • 3
  • 35
  • 40
4

Use compiler's flag, e.g. flag for GCC: -Wno-unused-variable

stacker
  • 87
  • 8
1

This works well but requires C++11

template <typename ...Args>
void unused(Args&& ...args)
{
  (void)(sizeof...(args));
}
Gian Lorenzo Meocci
  • 1,136
  • 2
  • 14
  • 23
  • 1
    What about this requires C++14 and would not work in C++11? I can't see anything. Also, it is discouraged to use `ALLCAPS` for anything except macros, which is to make them look ugly and undesirable, but there isn't anything bad about this, really, except that a `static_cast` would be nicer. – underscore_d Oct 27 '18 at 17:00
1

In C++11, this is the solution I'm using:

template<typename... Ts> inline void Unreferenced(Ts&&...) {}

int Foo(int bar) 
{
    Unreferenced(bar);
    return 0;
}

int Foo2(int bar1, int bar2) 
{
    Unreferenced(bar1, bar2);
    return 0;
}

Verified to be portable (at least on modern msvc, clang and gcc) and not producing extra code when optimizations are enabled. With no optimization, the extra function call is performed and references to the parameters are copied to the stack, but there are no macros involved.

If the extra code is an issue, you can use this declaration instead:

(decltype(Unreferenced(bar1, bar2)))0;

but at that point, a macro provides better readability:

#define UNREFERENCED(...) { (decltype(Unreferenced(__VA_ARGS__)))0; }
Nampo
  • 11
  • 2
0

I found most of the presented answers work for local unused variable only, and will cause compile error for unused static global variable.

Another macro needed to suppress the warning of unused static global variable.

template <typename T>
const T* UNUSED_VARIABLE(const T& dummy) { 
    return &dummy;
}
#define UNUSED_GLOBAL_VARIABLE(x) namespace {\
    const auto dummy = UNUSED_VARIABLE(x);\
}

static int a = 0;
UNUSED_GLOBAL_VARIABLE(a);

int main ()
{
    int b = 3;
    UNUSED_VARIABLE(b);
    return 0;
}

This works because no warning will be reported for non-static global variable in anonymous namespace.

C++ 11 is required though

 g++  -Wall -O3  -std=c++11 test.cpp
FaceBro
  • 787
  • 2
  • 13
  • 29
0
void func(void *aux UNUSED)
{
    return;
}

smth like that, in that case if u dont use aux it wont warn u

Scanel
  • 1
  • 1
0

define a macro for unused local variable:

#define UNUSED(x)  (void)((x))
Yossarian42
  • 1,950
  • 17
  • 14
-1

You can use __unused to tell the compiler that variable might not be used.

- (void)myMethod:(__unused NSObject *)theObject    
{
    // there will be no warning about `theObject`, because you wrote `__unused`

    __unused int theInt = 0;
    // there will be no warning, but you are still able to use `theInt` in the future
}
OlDor
  • 1,460
  • 12
  • 18
  • 2
    *Which* compiler? Because `__unused` is not standard C++, and more to the point, neither is what you posted... That's Objective-C. So this answer is only really useful for specific compiler(s), and it makes the code non-portable, and in fact not really valid since user code is not meant to use identifiers beginning with `__`, which are reserved for the implementation. – underscore_d Oct 27 '18 at 16:54
-16

I don't see your problem with the warning. Document it in the method/function header that compiler xy will issue a (correct) warning here, but that theses variables are needed for platform z.

The warning is correct, no need to turn it off. It does not invalidate the program - but it should be documented, that there is a reason.

Tobias Langner
  • 10,634
  • 6
  • 46
  • 76
  • 23
    The problem is that, if you have hundreds or thousands of such warnings, you might miss the one that is useful. (Twice I was in the situation to wade through several ten thousand warnings, eliminating most, and finding a few truly useful once that hinted at serious errors.) It's always good to compile without warnings, if possible on the highest warning level. – sbi Sep 28 '09 at 13:52
  • @sbi. Yes - if you have 100s or 1000s of such warnings then there is a danger that you'll miss the warnings that matter. However, is it really the case that people ever have 1000s of "this" warning against their code? – Richard Corden Sep 28 '09 at 15:05
  • 6
    In a project I worked on last year I turned on the highest warning level and got ~10,000 warnings. Only a few dozen were really helpful. Among those were hidden about a dozen really nasty bugs, but it took several man weeks to clean the code base to the point where one could actually _see_ the few serious ones. Had the warning level been up all the time and the code base been kept warning-free, those errors would never have crept into the code. – sbi Sep 29 '09 at 08:49
  • 1
    sorry - but doing the static code analysis (using whatever tool you have available, even if it's only the compiler) late in the project is a little bit like programming the whole program and when you finish, press compile and hope you have no errors. – Tobias Langner Sep 29 '09 at 09:40
  • @sbi: The question specifically refers to unused parameters. If you were saying that your code had ~10,000 unused parameter warnings then this would be an excellent point, but without more information it doesn't really help. – Richard Corden Sep 29 '09 at 11:19
  • 2
    @Richard: I worked on projects with thousands of source files. A little warning here and there, even well documented ones, quickly adds up. Even if you have only dozens of warnings flashing by during a build (instead of hundreds or thousands), having to look them up individually to see whether they are new ones or documented ones is too time-consuming and, in the end, won't be done. Therefor: Compile on the highest possible warning level with zero warnings. Every warning that comes up will be noticed immediately, looked at it, and either fixed or surpressed. – sbi Sep 29 '09 at 11:55
  • @Tobias: No static code analysis. Just the highest warning level for the normal compiler run. Yes, this example is extreme (although I have seen this happen several times in the last decade), but in extremeness it nicely shows the problem: If you have too many warnings flashing by, you don't see the important ones anymore. If it is just dozens instead of 10,000, the magnitude of the problem changes, but not the problem itself. – sbi Sep 29 '09 at 11:58
  • 2
    @sbi: turining on the highest warning level for your compiler is some form of static code analysis. Static code analysis is just reading the code without executing it and deducting information from it. That's exactly what the compiler does when he checks his rules for warnings. – Tobias Langner Sep 30 '09 at 05:56
  • @Tobias: Well, by this definition of the term (which I basically agree with), compiling with the lowest warning level is static code analysis, too – just a weaker one. _But anyway, that doesn't spoil my point:_ Had the highest warning level been turned on from the beginning with nobody caring for the warnings, the code would have had just as many warnings. The fact that there used to be less just showed that people tried to eliminate them – which is what I proposed. – sbi Sep 30 '09 at 15:54
  • @sbi: but that's my point. Turing on static analysis later in the project (or setting a higher level, ignoring warnings to fix them later, ...) is like writing the whole code without compiling/testing. The warnings are there for a reason. Use them - they'll find you bugs! Use them early, use them often. Use them at the highest level. – Tobias Langner Oct 01 '09 at 07:13
  • @Tobias: While you agree, this isn't what I was arguing against. You answer said "document the warning and ignore it" and I suggested "eliminate the warning" instead. When you end up with dozens, hundreds, thousands, or even ten thousands of warnings, the fact that all of them except one is documented doesn't help, because nobody is able to find that out. Now, whether you have thousands of warnings because you just turned on static analysis or because they accumulated in ten years, is orthogonal to my point. Mine was just a real-world example that happened to fall into the first category. – sbi Oct 01 '09 at 16:25
  • @sbi: document the warning and ignore it was meant for that specific warning that occurs in this case. If you have thousands of functions that have parameters that are not needed on one of the supported platforms, you messed up the design. It is not about the normal warnings you have because you messed up somewhere. You have to see the answer in the context of the question. The question was only about warnings because of unused variables on one of the supported platforms - not about warnings in general. – Tobias Langner Oct 02 '09 at 07:21
  • @TobiasLangner And his point is that just letting the warnings pile up like that makes it harder to miss important ones. Conversely, silencing it will _also_ serve as a form of documentation (if done properly), while hiding the warning until you're ready to deal with it. When you're ready to deal with it, just find all the files that have your silencer of choice. – Justin Time - Reinstate Monica Dec 30 '16 at 02:31