Which one of the following is preferrable and why when writing C macro?
Type 1
#define I2C_START() I2C_WAIT_IDLE(); SSP1CON2bits.SEN = 1
Type 2
#define I2C_START() \
do \
{ \
I2C_WAIT_IDLE(); \
SSP1CON2bits.SEN = 1; \
}while(0)
One of my colleagues prefers Type 1 while I prefer Type 2. So when both of us work in a project, both of the types are seen throughout the project.
-
\$\begingroup\$ c-faq.com/cpp/multistmt.html explains it in detail. \$\endgroup\$Alok– Alok2011年04月16日 04:20:20 +00:00Commented Apr 16, 2011 at 4:20
-
1\$\begingroup\$ This question appears to be off-topic because it is about best practice regarding a specific language feature. See help center. \$\endgroup\$200_success– 200_success2014年02月08日 17:28:13 +00:00Commented Feb 8, 2014 at 17:28
4 Answers 4
I prefer the second one because it can be used with normal compound stamens without modifications or accidentally being used incorrectly.
if (condition)
I2c_START;
Type 1: FAIL
Type 2: OK
Of course with good coding standards that can be avoided (always use '{' '}' on if). But every now and then people can be lazy (or just careless) and the second version prevents accidents from happening.
The best solution is not to use macros. Use functions and let the compiler work out when to inline.
Edited:
For billy: (Type 3) no do while
#define I2C_START() \
{ \
I2C_WAIT_IDLE(); \
SSP1CON2bits.SEN = 1; \
}
Unfortunately this fails if you use the else part of the if statement:
The trailing semi-colon (on type 3) marks the end of the if statement
thus else is not syntactically allowed. At least this gives you a compilation error unlike above. But Type 2 still works as expected.
if (condition)
I2C_START();
else
std::cout << "FAIL this test\n";
Type 1: FAIL
Type 2: OK
Type 3: FAIL
-
\$\begingroup\$ Well, you really don't need the "do" and "while (0)" bits for type 2 to prevent this though. A plain block will do just fine. \$\endgroup\$Billy ONeal– Billy ONeal2011年04月07日 04:23:59 +00:00Commented Apr 7, 2011 at 4:23
-
1\$\begingroup\$ It's syntax thing. Having only {} block will expand to if (...) { ... }; and spare ; is not good. \$\endgroup\$blaze– blaze2011年04月07日 07:17:37 +00:00Commented Apr 7, 2011 at 7:17
-
\$\begingroup\$ @blaze, really? You're worried about a semicolon that only the compiler will see, and ignore? \$\endgroup\$AShelly– AShelly2011年04月09日 01:54:50 +00:00Commented Apr 9, 2011 at 1:54
-
6\$\begingroup\$ @AShelly: if (foo) do { bar; } while 0; else { mmm; } = ok. if (foo) {bar} ; else {mmm;} = syntax error on else, because spare ; terminated if-statement. Oops :) \$\endgroup\$blaze– blaze2011年04月11日 10:01:59 +00:00Commented Apr 11, 2011 at 10:01
-
\$\begingroup\$ Ok, good point. \$\endgroup\$AShelly– AShelly2011年04月11日 19:09:58 +00:00Commented Apr 11, 2011 at 19:09
The Linux Kernel Newbies FAQ has an entry on this, since Linux uses it extensively. It's the syntax-safe way of defining these kinds of macros.
-
\$\begingroup\$ It would be good if you could actually put the content in your answer. \$\endgroup\$Frames Catherine White– Frames Catherine White2013年06月22日 09:30:19 +00:00Commented Jun 22, 2013 at 9:30
-
\$\begingroup\$ It's a long FAQ entry, sorry. \$\endgroup\$The UNIX Man– The UNIX Man2013年07月02日 02:19:37 +00:00Commented Jul 2, 2013 at 2:19
The second form is the safest without having to think too much about the consequences way.
but for what you are using it for? neither really need to be used. It should be a function. I'm taking it this is PIC code.... the overhead of the function call won't cost you that much.
-
\$\begingroup\$ yes it is pic. we typically write macros for 2/3 lines of register access. \$\endgroup\$Donotalo– Donotalo2011年04月08日 11:42:20 +00:00Commented Apr 8, 2011 at 11:42
I something similar to type two but without the do while as in:
#define I2C_START() \
do \
{ \
I2C_WAIT_IDLE(); \
SSP1CON2bits.SEN = 1; \
}while(0)
The do while could be difficult to understand for an inexperienced coder. I also always use {} even for onliner if
statements.
-
\$\begingroup\$ any inexperience coder should learn what do{}while(0) does. \$\endgroup\$Donotalo– Donotalo2011年05月05日 12:22:45 +00:00Commented May 5, 2011 at 12:22
-
\$\begingroup\$ Yes. But by keeping it obvious and simple you avoid problems with people that have not or do not want to learn. \$\endgroup\$Gerhard– Gerhard2011年05月06日 05:39:14 +00:00Commented May 6, 2011 at 5:39