tags:

views:

881

answers:

9

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?

+19  A: 

You can put in 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);
}
Alex B
+1 - still I would document why you don't use the variable even if it's there.
Tobias Langner
+4  A: 

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
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
AProgrammer, the code doesn't look like `c` at all to me ;-)
Michael Krelin - hacker
@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
A: 

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
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
@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
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
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
@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
@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
@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
@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
@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
@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
@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
@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
+8  A: 

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
Just to reinforce this answer - you don't need the #ifdef, just comment out the unused parameter names.
quamrana
+2  A: 

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)

Behrang Dadsetan
"Using preprocessor directives is considered evil most of the time." Really? By who?
Graeme Perrow
By anyone who cares about scope, being able to debug properly, or their sanity.
Bill
@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.
Behrang Dadsetan
+1  A: 

In gcc, you can use the __attribute__((unused)) preprocessor directive you achieve your goal. Example:

int foo (__attribute__((unused)) int bar) {
   return 0;
}
ezpz
A: 

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
+1  A: 

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.

Sean Farrell
+1  A: 

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))
michael burton