Go Back   MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Reply
 
Thread Tools Search this Thread Display Modes
Old Feb 21, 2013, 08:13 PM   #1
ArtOfWarfare
macrumors 603
 
ArtOfWarfare's Avatar
 
Join Date: Nov 2007
Send a message via Skype™ to ArtOfWarfare
Any thoughts on the comma operator (C/C++/Obj-C?)

I recently decided to insert a few comma operators into the output lines of my C++ code and I feel like they've cleaned up my code a lot.

For example, I had this code:

Code:
cout << "Can't place " << v << " at " << x << ", " << y << endl << "Add: ";
printBitsForInt(mask);
cout << "Old: ";
printBitsForInt(conflicts[v-1]);
cout << endl;
Just an FYI, printBitsForInt() takes an int and prints out the bits from it. I couldn't find any way to overload the insertion operator between a stream and an int (because it's already defined by C++.) I couldn't find any stream parameters for cout I could set to make it print ints as binary, either. I tried using a bitset container, but it didn't allow its contents to be printed out with the grouping I wanted (groups of nine bits with spaces between them.)

And by introducing a few sequence points I feel like I was able to clean it up quite a bit, improve legibility, and reduce the amount of space it takes up.

Code:
cout << "Can't place " << v << " at " << x << ", " << y << endl
     << "Add: ", printBitsForInt(mask), cout << endl;
     << "Old: ", printBitsForInt(conflicts[v-1]), cout << endl;
I'm a little confused why I so rarely see anyone using them.

I'm wondering if I could use the same basic idea in the future with some C or Obj-C code.

Also, is there any real difference between using the comma operator and inserting a semicolon? I feel like the compiler probably generates the same code for both, wouldn't it?

Are there any other good uses for the comma operator?
__________________
Don't tell me Macs don't last: 2007 iMac, 2007 Mac Mini, 2008 MacBook Air, all Vintage.
(iMac obsoletion: April 28, 2015, MBA: October 14, 2015, Mac Mini: March 9, 2016)
ArtOfWarfare is online now   0 Reply With Quote
Old Feb 21, 2013, 08:26 PM   #2
gnasher729
macrumors G5
 
gnasher729's Avatar
 
Join Date: Nov 2005
Quote:
Originally Posted by ArtOfWarfare View Post
I recently decided to insert a few comma operators into the output lines of my C++ code and I feel like they've cleaned up my code a lot.
I felt like that for a very short period after learning C. Then I felt it made the code less readable.

Quote:
Originally Posted by ArtOfWarfare View Post
Also, is there any real difference between using the comma operator and inserting a semicolon? I feel like the compiler probably generates the same code for both, wouldn't it?
There's no reason why the code would be different.

Quote:
Originally Posted by ArtOfWarfare View Post
Are there any other good uses for the comma operator?
Very, very rare. This would be an example:

Code:
while (tmp = x*x + y*y, tmp > 10 && tmp < 20) { ... }
instead of

Code:
for (;;) {
    tmp = x*x + y*y; 
    if (tmp <= 10 || tmp >= 20) break;
    ...
}
gnasher729 is online now   0 Reply With Quote
Old Feb 21, 2013, 10:52 PM   #3
lee1210
macrumors 68040
 
lee1210's Avatar
 
Join Date: Jan 2005
Location: Dallas, TX
I've never felt the need to use it, I've rarely seen it at all, really. Executing multiple statements in the incrementor of a for, etc. is a rare but useful case. I had to fix one very pernicious bug caused by a comma operator, which put it into my bad graces.

As for the difference between ; and , is that ; ends a statement and , joins statements and evaluates to the right operand.
x = haveFun(), eatPie(), takeNap();
Will result in x being set to the result of takeNap().

I'm not big on C++, but %b is the format specifier for printing the binary representation of an int. Why not return a std::string from your helper, then just keep using <<. Having the function print after formatting that way limits the utility.

-Lee

Edit: figured there was a better way. Try:
cout << setbase(2) << myInt << endl;

Last edited by lee1210; Feb 21, 2013 at 10:58 PM.
lee1210 is offline   0 Reply With Quote
Old Feb 21, 2013, 11:47 PM   #4
chown33
macrumors 603
 
Join Date: Aug 2009
Quote:
Originally Posted by gnasher729 View Post
Very, very rare. This would be an example:

Code:
while (tmp = x*x + y*y, tmp > 10 && tmp < 20) { ... }
instead of

Code:
for (;;) {
    tmp = x*x + y*y; 
    if (tmp <= 10 || tmp >= 20) break;
    ...
}
I used to write loops like the former, or try to. Then I spent way too much time trying to figure them out weeks later, or trying to debug them at the time. Now I only do it like the latter (though I usually put the break on its own indented line).


My thoughts regarding the comma operator:
1. It can make it difficult to set a breakpoint at a statement, if the statement is a bunch of comma-separated expressions. Better to make each one a separate statement.

2. There were times when an aggressive optimizer wouldn't rearrange the parts of a comma'ed statement, but it would rearrange statements with semicolons. I don't know how true that is any more, since optimizers are a lot better these days. Still, it wouldn't surprise me if commas aren't entirely interchangeable with semicolons when it comes to code rearrangement.

3. If you want to add something between the comma'ed expressions, it gets ugly very quickly. Even when the expressions may seem to be inseparable in the design, things can evolve and change over time.

4. One place where I still use commas is in the initializer (1st) or the iterator (3rd) clauses of a for loop, e.g.:
Code:
for ( a = x, b = y;  someCondition;  ++a, --b )
{  something using both a and b;  }
The fact that a continue in a for loop will go to the iterator part means that if there's more than one iterative calculation, you can guarantee that both are always done. However, there are also times when you DON'T want both things done, and for that I'd probably write it as a for (;;) so every conditional pathway was easy to follow.


EDIT
Quote:
Originally Posted by lee1210 View Post
As for the difference between ; and , is that ; ends a statement and , joins statements and evaluates to the right operand.
Code:
x = haveFun(), eatPie(), takeNap();
Will result in x being set to the result of takeNap().
I think the underlined part is incorrect. Assignment binds tighter than comma, so the assignment is done first, then eatPie() is called, then takeNap(). Effectively:
Code:
(x = haveFun()), eatPie(), takeNap();
If this precedence weren't so, then this expression wouldn't work:
Code:
a = x, b = y
Since functions that return values can have the value ignored with little or no compiler complaint, the fact that takeNap() returns a value that's ignored would not cause the compiler to warn about it. Unexpected results ensue.

I don't have the time right now to write up a test case, but doing so would prove enlightening on several levels. One level is the fundamental operation of comma: its precedence, associativity, debuggability, etc. Another level is the potential confusion or errors when using it, even for skilled programmers with years of experience. I include myself in that bunch of confused error-makers, because I could be wrong. It's exactly the kind of thing I'd only trust after writing test code for, and frankly, if I have to write a test to figure out how it works, is it really worth using in real-world code? I could name all my variables as nothing but different numbers of _'s, too, but why would I do that except to sow confusion?

Last edited by chown33; Feb 22, 2013 at 12:35 AM.
chown33 is offline   0 Reply With Quote
Old Feb 22, 2013, 01:38 AM   #5
lee1210
macrumors 68040
 
lee1210's Avatar
 
Join Date: Jan 2005
Location: Dallas, TX
Oops, there you go.
Code:
x = (haveFun(),eatPie(),takeNap());
Works the way I was thinking. Screwed up the precedence, but was right about the second operand being the result.

One more data point for myself generally avoiding the , operator. Clauses in a for loop are the rare exception.

-Lee
lee1210 is offline   0 Reply With Quote
Old Feb 22, 2013, 02:27 AM   #6
gnasher729
macrumors G5
 
gnasher729's Avatar
 
Join Date: Nov 2005
Quote:
Originally Posted by chown33 View Post
1. It can make it difficult to set a breakpoint at a statement, if the statement is a bunch of comma-separated expressions. Better to make each one a separate statement.
That's a very important argument. Making your code easy to debug is very important. I tend to write code with "setting breakpoints" in mind. For example: The first one doesn't let you easily examine the result of calling f (x), the second does.

Code:
return f (x);
Code:
int result = f (x);
return result;

Last edited by gnasher729; Feb 22, 2013 at 08:09 AM.
gnasher729 is online now   1 Reply With Quote
Old Feb 22, 2013, 05:42 AM   #7
whooleytoo
macrumors 603
 
whooleytoo's Avatar
 
Join Date: Aug 2002
Location: Cork, Ireland.
Send a message via AIM to whooleytoo
Yikes. I'm ashamed to admit after years of study and more years of development work on C-esque languages, I'd never even heard of the comma operator.

I'm kind of glad I didn't though. If there's one thing I've learned through experience it's the importance of code maintainability, and having easily readable and debuggable code is far, far more important than keeping code terse.

Even reading through the Wikipedia, the simple examples gave me a shiver:
i = (a,b); // b
i = a,b; // a

I can see how one of those lines, buried in hundreds of lines of code, could introduce an easily missed bug.
__________________
Mac <- Macintosh <- McIntosh apples <- John McIntosh <- McIntosh surname <- "Mac an toshach" <- "Son of the Chief"
whooleytoo is offline   0 Reply With Quote
Old Feb 22, 2013, 07:42 AM   #8
960design
macrumors 6502a
 
Join Date: Apr 2012
Location: Destin, FL
Occasionally, I'll come up with an amazing line of code that is pure poetry. I take a sip of tea, then break the line into about 30 separate lines of easily readable code and let the compiler do it's job of making the executable efficient.

Coming back to fix something 4 months and 6 projects later on poetry is a serious PITA.
__________________
TI-99/4A, tape cassette, 12" B&W Zenith
960design is offline   1 Reply With Quote
Old Feb 22, 2013, 08:12 AM   #9
gnasher729
macrumors G5
 
gnasher729's Avatar
 
Join Date: Nov 2005
Quote:
Originally Posted by whooleytoo View Post
Even reading through the Wikipedia, the simple examples gave me a shiver:
i = (a,b); // b
i = a,b; // a

I can see how one of those lines, buried in hundreds of lines of code, could introduce an easily missed bug.
That's why you turn on all compiler warnings that you can. i = a, b; doesn't even compile on my Mac (it produces a warning because the value b is ignored, and I turn all warnings into errors).
gnasher729 is online now   0 Reply With Quote
Old Feb 22, 2013, 01:33 PM   #10
notjustjay
macrumors 603
 
notjustjay's Avatar
 
Join Date: Sep 2003
Location: Canada, eh?
Quote:
Originally Posted by lee1210 View Post
I had to fix one very pernicious bug caused by a comma operator
This is why I tend not to go for "clever" code. I work on a codebase that's huge (500K+ lines), historical (some of this code was written in the 80's) and maintained by dozens of people. Code I wrote today might be maintained by someone else 6 months from now when I transfer to a different project. Likewise, I'll frequently inherit code written 4 years ago by other programmers who no longer work with the company.

To me, good code is cleanly formatted, straightforward, and easy to follow (with comments where helpful). If I have to stop and say "wait wait wait, what is this doing?" then that slows things down and potentially allows bugs to go unnoticed.
__________________
.
notjustjay is offline   1 Reply With Quote
Old Feb 22, 2013, 01:54 PM   #11
ArtOfWarfare
Thread Starter
macrumors 603
 
ArtOfWarfare's Avatar
 
Join Date: Nov 2007
Send a message via Skype™ to ArtOfWarfare
Quote:
Originally Posted by lee1210 View Post
Edit: figured there was a better way. Try:
cout << setbase(2) << myInt << endl;
Huh. Can I have it put a space after every 9th bit/digit?
__________________
Don't tell me Macs don't last: 2007 iMac, 2007 Mac Mini, 2008 MacBook Air, all Vintage.
(iMac obsoletion: April 28, 2015, MBA: October 14, 2015, Mac Mini: March 9, 2016)
ArtOfWarfare is online now   0 Reply With Quote
Old Feb 22, 2013, 03:58 PM   #12
lee1210
macrumors 68040
 
lee1210's Avatar
 
Join Date: Jan 2005
Location: Dallas, TX
Quote:
Originally Posted by ArtOfWarfare View Post
Huh. Can I have it put a space after every 9th bit/digit?
You can probably write your own modifier, but otherwise I'd just write a formatter that returns what you want to print. I'll happily admit that I don't know the right way to do this safely as it pertains to memory in C++, but surely this is a solved problem.

-Lee
lee1210 is offline   0 Reply With Quote
Old Feb 26, 2013, 04:46 AM   #13
knightlie
macrumors 6502a
 
Join Date: Feb 2008
Quote:
Originally Posted by whooleytoo View Post
Even reading through the Wikipedia, the simple examples gave me a shiver:
i = (a,b); // b
i = a,b; // a
Wow.
__________________
2011 Mac Mini i5 | iPad Mini | Wife | Cat
knightlie is offline   0 Reply With Quote

Reply
MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Similar Threads
thread Thread Starter Forum Replies Last Post
iPad: Exclamation point instead of comma when I type flyersgl iPad 1 Dec 28, 2013 03:01 AM
convert comma to decimal point in excel userjoy Mac Applications and Mac App Store 5 Feb 14, 2013 06:54 AM
# arithmetic operator for Bash BerGaur OS X 1 Dec 16, 2012 08:14 AM
4S - no operator signal Moccasin iPhone Tips, Help and Troubleshooting 0 Jul 11, 2012 10:58 PM
Removing comma from a list fhill2 Mac Programming 8 Jun 25, 2012 12:07 PM

Forum Jump

All times are GMT -5. The time now is 12:09 PM.

Mac Rumors | Mac | iPhone | iPhone Game Reviews | iPhone Apps

Mobile Version | Fixed | Fluid | Fluid HD
Copyright 2002-2013, MacRumors.com, LLC