0

So I've read this question and other related questions, and I know that it's a good idea to check the return value of scanf to avoid surprises. But I have the following scanf in my code:

/*
 * If we don't gobble newlines,
 * then they'll be interpreted as commands.
 * Gobble both \n and \r (because the input files use 0x0D).
 */
(void) scanf("%*[\n\r]");

As you can see, I'm casting the result of scanf to void, but GCC still warns under -ansi -pedantic -Wall -O3, as noted here.

Is there anything clean I can do to suppress this warning without compiler-specific directives—that is, in pure ANSI C90? (By clean I mean no if (scanf(...)); or similar.)

Community
  • 1
  • 1
wchargin
  • 15,589
  • 12
  • 71
  • 110
  • how about writing a function called ignore and going ignore(scanf(...)); – pm100 Feb 06 '15 at 02:46
  • Maybe I'm not understanding your question, but what's wrong with `int foo = scanf(...)`? – Carey Gregory Feb 06 '15 at 02:52
  • @CareyGregory (1) it's misleading, because I *don't* care about the return value and *won't* use `foo`, and (2) that would still create an unused variable warning. – wchargin Feb 06 '15 at 02:56
  • I can't reproduce this. What version of GCC? –  Feb 06 '15 at 02:57
  • 1
    Okay, but what would happen if `scanf` actually did fail? That's not at all hard to accomplish when you hit `EOF`, so why go to extreme lengths to completely ignore the return value without warnings? – Carey Gregory Feb 06 '15 at 02:58
  • and, of course, kudos for -wall (and caring). No -werror? thats what sorts the true fanatics – pm100 Feb 06 '15 at 03:14
  • @pm100 my `-Werror` is internal :) – wchargin Feb 06 '15 at 03:21

1 Answers1

2

GCC 4.4 does warn in this case, but 4.7 and 4.9 do not. This lines up with the claim in that GCC bug you linked that it was fixed in 4.5. So one option is to use a version of the compiler less than five years old.

If you're stuck with GCC 4.4 or older, you can do this:

int dummy = scanf("%*[\n\r]");
(void)dummy;

This should be a familiar pattern to many C or C++ programmers.

If for some reason you object to using two statements and don't want to create an ignore() function as suggested by @pm100, you could also do this:

abs(scanf("%*[\n\r]"));

I would much prefer the (void)dummy solution though.

Finally, you could avoid scanf() altogether and do something like this (untested, not 100% sure it does what you need):

int ch;
do {
  ch = getchar();
} while (ch == '\r' || ch == '\n');
ch = ungetc(ch, stdin);
assert(ch != EOF);

Obviously you'd put that all in a nice little function with a descriptive name, which is probably a good idea with the scanf() solutions too.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • I have gcc 4.8.2—is this not covered for some reason? – wchargin Feb 06 '15 at 03:16
  • On what platform? 4.7 and 4.9 work for me. Anyway it doesn't really matter, just apply one of the fixes and move on. – John Zwinck Feb 06 '15 at 03:19
  • It's gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2. You're right that it's not super important, but it seems weird for 4.7 and 4.9, but not 4.8, to be covered. – wchargin Feb 06 '15 at 03:20
  • I think your loop is broken and should be more like: `while ((ch = getchar()) != EOF && ch != '\n' && ch != '\r') ;` (where I'd have the semicolon on a line on its own if I could format a comment!). – Jonathan Leffler Feb 06 '15 at 05:12