Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Coral Kashri
Coral Kashri

Posted on • Originally published atcppsenioreas.wordpress.com on

     

It’s just ‘,’ – The Comma Operator

We all know that every ‘,’ matters in this language, so I decided to talk directly about that character today. So, how much impact can be for such a small little character?

The Comma Operator

This operator comes from C, where it tells the compiler to evaluate all the expressions (left to right) and to return the result of the latest evaluated expression. For example:

inta,b;a=5,b=4,b+=a,++a,std::cout<<b<<" "<<a;// Prints 9 6
Enter fullscreen modeExit fullscreen mode

Another example of that operator usage is as follows:

for(size_ti=0,k=500;i<10;++i,++k){/*...*/}
Enter fullscreen modeExit fullscreen mode

We can see this operator in action in the third section of thefor statement. It evaluates the++i and then evaluates++k.

Not Every Comma is The Comma Operator

Although it might be confusing, not every comma we see in our code uses the comma operator. For example, when we pass parameters into functions, define the arguments we want to pass to the template or declare multiple objects using commas, these cases do not use the comma operator. Moreover, in the cases of passing arguments to functions, the evaluation order is not defined. Examples:

template<typenameT,typenameV>voidfunc(int,int,int);inta=5,b=6,c=7;// Not the comma operatorfor(inti=1,j=2;i<5;++i);// Not the comma operatorfunc<int,float>(a,b,c);// Not the comma operator
Enter fullscreen modeExit fullscreen mode

At this point, some of you might think there is no reason to be afraid of such an operator, if all it does is evaluate expressions left to right. Well, we are talking about C++ here, and I think it’s time to move to the spooky sides of this operator.

Fold Expressions

Another known usage of the comma operator is as part offold expressions (Since C++17). To apply multiple unrelated expressions on the variadic parameters, we can use the comma operator as in the following example:

template<typename...ArgsF>voidcall_functions(ArgsF&&...argsf){(argsf(),...);}/*...*/call_functions([]{std::cout<<"Func1\n";},[]{std::cout<<"Func2\n";},[]{std::cout<<"Func3\n";});
Enter fullscreen modeExit fullscreen mode

The ‘,’ is out there

About a year ago someone published onReddit the following example:

for(inti=0;i<10,000;i+=1)
Enter fullscreen modeExit fullscreen mode

At first glance, there is nothing wrong with this code, and yet this loop will perform 0 iterations.

The comma operator is attached between the following expressions:i < 10 and000. Therefore it performs the left expression and evaluates true and then performs the right expression, evaluates false, and returns the latter.

Let’s look for another example:

intx=5,y=6,z;z=(x,y);
Enter fullscreen modeExit fullscreen mode

In this example, the two expressions arex andy. The compiler first evaluatesx and theny and returns the latter. But what would happen if we remove the parentheses?

intx=5,y=6,z;z=x,y;
Enter fullscreen modeExit fullscreen mode

Well, this time the expressions arez = x andy. The exact opposite of the previous example.

Dangerous Yesterday, Powerful Today

Before C++23, subscript expression (operator[]) could accept only a single argument. The following example is legal until C++20:

classContainer{public:int&operator[](inta){/*...*/}};...Containerc;c[1,4]=5;// <--
Enter fullscreen modeExit fullscreen mode

This mistake might make someone believe it’s about accessing a specific cell in a matrix located in row 1 column 4, when it actually ignores the1 and passes only the number4 to the operator function.

Since C++20 using the comma operator without parentheses (()) inside subscript expressions isdeprecated, and since C++23 it’s illegal as the operator might accept more than one parameter and the compiler will generate a matching error to a wrong number of parameters.

In C++23 we can see an example of the usage of this new language ability in the implementation ofmdspan (which was part of the motivation for this ability).

Usage example with parentheses:

Containerc;c[(1,4)]=5;// The intention is clear: Only one parameter is passed to the operator.
Enter fullscreen modeExit fullscreen mode

Overloading Comma Operator

Now that we understand the basic risk of using the comma operator, it’s time to have some fun with it and stretch the limits of this pranking operator.

template<typenameT>std::ostream&operator,(std::ostream&out,Tval){returnout<<val;}intmain(){std::cout,"hello ","world ",42;// Prints "hello world 42"return0;}
Enter fullscreen modeExit fullscreen mode

Yes, it’s legal. But we can stretch the rules a little bit further:

template<typenameT,typenameP>Toperator,(Tlhs,Prhs){returnlhs;}intmain(){intx=5,y=6,z;z=(x,y);std::cout<<z;// Prints 6std::stringstr1="5",str2="6",str3;str3=(str1,str2);std::cout<<str3;// Prints 5return0;}
Enter fullscreen modeExit fullscreen mode

This time it’s a little bit more confusing: Why does the new overload have no effect on the first case, and does have an effect on the second one?

The reason is that the comma operator overload (and any other operator’s overloading) has to accept at least one parameter of class or enumeration type. Therefore the instantiation ofint operator,(int, int) is not legal and doesn’t apply to the first case (which uses the regular rule of comma operator).

If you also insist on forcing the first example to work by the new rule, we can make a little change:

structMyInt{MyInt(inta):a(a){}operatorint(){returna;}inta;};/*...*/MyIntx=5,y=6;intz;z=(x,y);std::cout<<z;// Prints 5
Enter fullscreen modeExit fullscreen mode

And a little bit of strings math:

usingnamespacestd::string_literals;intoperator,(std::string_views1,std::string_views2){std::cout<<s1<<" "<<s2;returns1[0]+s2[0];}intmain(){std::cout<<("Hello"s,"World\n")+("What's"s,"Up\n")*("Nicely"s,"Done\n")<<"\n";"This"s,"is"," so"s,"cool";return0;}/* Output: */HelloWorldWhat'sUpNicelyDone25271Thisissocool
Enter fullscreen modeExit fullscreen mode

Approaching large numbers without this operator

In math, we used to separate large numbers using commas. As we can’t use this approach in C++, we have to use other methods to help us with readability and maintainability issues.

Since C++14 we can use a single quote to split a number into multiple sections (cppreference):

unsignedlonglongl1=18446744073709550592ull;// C++11unsignedlonglongl2=18'446'744'073'709'550'592llu;// C++14unsignedlonglongl3=1844'6744'0737'0955'0592uLL;// C++14unsignedlonglongl4=184467'440737'0'95505'92LLU;// C++14
Enter fullscreen modeExit fullscreen mode

Another strategy is to use the literale (orE) followed by a number. This means you multiply the number beforee by 10 raised to the power of the number aftere. For example:

inta=10e3;// Equals to: 10,000floatb=15e-3;// Equals to: 0.015intc=15.3e6;// Equals to: 15,300,000
Enter fullscreen modeExit fullscreen mode

Conclusion

The comma operator is useful for separating commands inside a limited section. However, it’s a highly dangerous operator with non-obvious actions and meanings sometimes. If you see a usage of this comma operator, don’t ignore it and suspect it might cause an unseen problem.

The best practice for this particular operator is to avoid it as much as you can and prefer alternatives as much as possible. This operator can cause real damage, as shown in this article, even with subtle changes in the code.

Special thanks toYehezkel Bernat &Ellie Bogdanov for reviewing & comments.

This article originally published on my personal blog:C++ Senioreas.

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

She/Her | FS developer - mainly Linux C++ RT developer.
  • Location
    Israel
  • Education
    Self educated & Practical Software Engineer
  • Pronouns
    She/Her
  • Work
    Senior C++ RT developer / Software architect
  • Joined

More fromCoral Kashri

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp