4

I was reading some material about errors that should be avoided when writing C programs and I came across the following code:

#include <stdio.h>

void foo(int param)
{
  printf("foo is called\n");
  printf("%d\n",param);
}

int main()
{
  return foo,(1);
}

The code above build without errors and warnings (it only show a warning when -Wall is activated) but when I run the small program nothing is displayed. The function foo is not called because of the comma separator.

My question is why the C standard allow such syntax? Shouldn't the compiler issue an error in this case? In which context this syntax could be used in some real use case?

Thanks in advance,

PD: I'm using GCC 4.8.3

EDIT:

Couldn't the compiler in this case detect the situation and issue an error instead of warning (as I said it only appears when -Wall is enabled)

sepp2k
  • 363,768
  • 54
  • 674
  • 675
rkachach
  • 16,517
  • 6
  • 42
  • 66
  • 1
    https://en.wikipedia.org/wiki/Comma_operator – larsks Sep 30 '15 at 15:26
  • Perfectly valid - read up about the comma operator – Ed Heal Sep 30 '15 at 15:27
  • Yes, but this doesn't answer the other questions. Why the compiler doesn't throw an error in this case, etc .. and specially in which case such syntax could be useful. – rkachach Sep 30 '15 at 15:30
  • It doesn't throw an error because the comma operator in `foo,(1);` is syntactically equivalent to the same operator in `i = 0, j = 0;`. – R_Kapp Sep 30 '15 at 15:32
  • So, in this case it's not an error prone situation. In the example case it's clear that it's separating a function call and it's arguments. Why the compiler in this case doesn't issue an error? is it hard to detect? – rkachach Sep 30 '15 at 15:34
  • What is the warning you get? It should provide a clue as to why it doesn't issue an error. – R_Kapp Sep 30 '15 at 15:38
  • "left-hand" operand of comma expression has no effct". I mean the warning (when -Wall enabled) is good. But couldn't the compiler detect in this case that a programmer made an error and is calling a function in the wrong way? .. so in this case issue an error instead of a warning! – rkachach Sep 30 '15 at 15:40
  • The idea is, the compiler has no idea that you're calling a function; how should it? – R_Kapp Sep 30 '15 at 15:47
  • The compiler knows that foo is a function, otherwise it would issue an error. Since following we get a "(" then I think it should be enough to guess what the programmer is trying to do. – rkachach Sep 30 '15 at 15:50

4 Answers4

5
return foo,(1);

is equivalent to:

foo; // Nothing happens. This does not call the function.
return (1);

Perhaps you meant to use:

foo(1);
return 1;
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Thanks for the response. But the question asks more about why the syntax is allowed for this kind of situations (when it's clear that the programmer is introducing an error). – rkachach Sep 30 '15 at 15:45
  • @redobot, the compiler has to allow the syntax since it is legal by the standard of the language. There are so many pitfalls in the language that are worse than this. The number of ways a program will exhibit undefined behavior is rather long. The compiler allows them too. Compared to them, this is rather harmless. – R Sahu Sep 30 '15 at 15:51
5

C is a simple, minimalist language where the programmer is supposed to know what they're doing.

In C, types convert to each other quite easily and the original C didn't even have function declarations -- the programmer was supposed to know how to call each function and with what parameters.

C was the programming language for Unix and

"UNIX was not designed to stop you from doing stupid things, because that would also stop you from doing clever things."—Doug Gwyn (https://en.wikiquote.org/wiki/Unix)

As a bonus, if the compiler doesn't try to be smart, compilation can be very fast.

C++ takes a very different approach to this.

As for practical applications of the , operator, take a look at: https://en.wikipedia.org/wiki/Comma_operator

The comma operator has relatively limited use cases. Because it discards its first operand, it is generally only useful where the first operand has desirable side effects. Further, because it is rarely used outside of specific idioms, and easily mistaken with other commas or the semicolon, it is potentially confusing and error-prone. Nevertheless, there are certain circumstances where it is commonly used, notably in for loops and in SFINAE (http://en.cppreference.com/w/cpp/language/sfinae). For embedded systems which may have limited debugging capabilities, the comma operator can be used in combination with a macro to seamlessly override a function call, to insert code just before the function call.

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
4

foo,(1); first evaluate foo and do nothing, then evaluate (1) and do nothing.

The comma operator is useful, for example, when you do multiple things in for loop.

int i, j;
for (i = 0, j = 1; i < 10; i++, j *= 2) {
    printf("%d %d\n", i, j);
}
MikeCAT
  • 73,922
  • 11
  • 45
  • 70
2

It appears the exercise and sample code was designed specifically to highlight the particular use, pitfalls, and human fallibility when reading, a sequence of operations chained together with the comma operator.

There is nothing wrong with the comma operator, but it is more of a shortcut or hack to save a line or two of code and avoid having to wrap a two expression loop or conditional in braces.

You stumbled into exactly what the writer wanted you to stumble into in the exercise. Your eyes read right past the fact that there were no parenthesis following foo by virtue of the comma operator, with the only applicable return being 1.

It is a good example. Why? Learning has occurred -- not only regarding the comma operator, but your learning that the warnings were only disclosed if you use -Wall when you compile your code (you should add -Wextra as well). All examples can only hope to do as well.

To complete the example, look at the working application of the comma operator in that situation. (the bonus -- if you caught it before compiling and running the example)

#include <stdio.h>

void foo(int param)
{
    printf("foo is called\n");
    printf("%d\n",param);
}

int main()
{
    //return foo,(1);
    return foo(0),1;
}

Output

$ ./bin/commafoo
foo is called
0

$ echo $?
1

So, yes, the comma operator does have its place, but it is rarely, if ever, required.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • Also likely is that "return foo(1);" was what the code was supposed to be, and this example was created to show what can happen when there is an inadvertent typo (the comma) – FredK Sep 30 '15 at 16:49
  • Good point as well. But a misplaced `,` kinda minimizes focus on the comma operator and emphasizes careful typing. 6-to-one, 1/2 dozen-to-another I guess `:)` – David C. Rankin Sep 30 '15 at 17:01