1

Give me an idea please, when one can use comma as a delimiter and when only semicolon:

typedef struct k{int a,b;}*K;
main() {
  K z=(K)malloc(2*sizeof(int));
  z->a=1, // <- may be ; or , at the eol
  // This seems not like a multi-variables definition of same type vars, so why ',' is good?
  z->b=2;
  free(z);
  return 0;
}
egor7
  • 4,678
  • 7
  • 31
  • 55
  • @kaylum That's a question for JavaScript! Do not use questions about wildly different languages as close vote duplicate targets! – Lundin Feb 14 '20 at 09:29
  • @Lundin Sorry, honest mistake. – kaylum Feb 14 '20 at 09:31
  • @kaylum Might want to withdraw any dupe close votes in case you cast any. – Lundin Feb 14 '20 at 09:31
  • 2
    How about this: [Effect of using a comma instead of a semi-colon in C and C++](https://stackoverflow.com/questions/2087026/effect-of-using-a-comma-instead-of-a-semi-colon-in-c-and-c) – kaylum Feb 14 '20 at 09:37
  • regarding: `main() {` this does not (cleanly) compile. There are only two valid signatures for `main()` they are: `int main( void )` and `int main( int argc, char *argv[] )' Notice that they both have a return type of `int` – user3629249 Feb 15 '20 at 18:38
  • OT: regarding: `typedef struct k{int a,b;}*K;` 1) the first semicolon `;` can/should be completely eliminated. 2) do not hide pointers in `typedef` statements – user3629249 Feb 15 '20 at 18:40
  • OT: for ease of readability and understanding: 1) insert a reasonable space: inside braces, inside parens, inside brackets, after semicolons, after commas, around C operators – user3629249 Feb 15 '20 at 18:42
  • OT: regarding; `K z=(K)malloc(2*sizeof(int));` 1) in C, the returned type is `void*` which can be assigned to any pointer. Casting just clutters the code. Suggest removing that cast. 2) always check (!=NULL) the returned value to assure the operation was successful. if not successful, call `perror( "malloc failed" );` to output both the error message and the text reason the system thinks the error occurred to `stderr`. This is an unrecoverable error, so (probably) should also call: `exit( EXIT_FAILURE );` – user3629249 Feb 15 '20 at 18:45

2 Answers2

5

First of all, you must realize that you are using the comma operator here. See What does the comma operator , do?

There is no practical difference between the comma operator and semicolons. The key here is to understand sequence points, an abstract C term for points in the source where all previous evaluations must be done. A semicolon always introduces a sequence point, but so does the comma operator. That's why your code works and why z->a=1 is guaranteed to be executed ("sequenced") before z->b=2.

However, using the comma operator leads to strange, hard-to-read code. It is often confused with commas in initializer lists or function call parameter lists. In your comment, you confuse this for a multiple variable initialization.

As a rule of thumb, the comma operator should not be used at all, except for very specialized cases.

The main use of the comma operator and the reason why it is still in the language, is that it allows for function-like macros that do multiple things but still return a value like a function. Example:

#include <stdio.h>

int foo (void)
{
  puts("hello world");
  return 1;
}

#define foo() (puts("mocking function foo"), 2)

int main()
{
  printf("%d", foo());
  return 0;
}

Here a macro is completely replacing the function with the same name (known as "function mocking"), but keeps the calling API intact, which might be useful for debug and test purposes. There's a place for the comma operator in special-purpose macros like these.

Lundin
  • 195,001
  • 40
  • 254
  • 396
1

I want to add that the comma operator allows for some IMHO quite beautiful code, such as:

 if (a = foo(), a != -1) {
 }

Instead of

 if ((a = foo()) != -1) {
 }

However, not many actually know about the comma operator, so you're perhaps better of not using it, sadly.

ljrk
  • 751
  • 1
  • 5
  • 21