Difference in the style of giving comments between C and C++ - c++

Is there any difference between a commenting style between C(/*..*/) and C++(//)?
MISRA C:2004 says
Rule 2.2 (required): Source code shall only use /* … */ style
comments.
Note: This Rule is revoked for MISRA C:2012 when support for C99 was added
MISRA C++ says
Rule 2.7.1 (required): The character sequence /* shall not be used
with c style comments.
Rule 2.7.3 says suggested comment as // for c++
Can any one explain why MISRA says to use /* in C and // in C++?

The MISRA C clause you quote requires that "line comments" of the form
// This is a line comment
not be used, in favour of a "C-style" comment of the form
/* Original C style comment
Can extend across multiple lines
*/
This allows older compilers to be used, since the "line comment" was only introduced in 1999, and was only available with some compilers before then as a non-standard extension.
The MISRA C++ clause you quote (from memory, there is a similar one in MISRA C) requires that the "original C-style comment" shall not be nested. So, this is discouraged
/* Warning: non-standard nesting of comment
/* Nested comment
*/
*/
This is discouraged because support for it is not standard, but some compilers can be configured to support it. Code which uses "nested comments" can therefore behave differently (including compiling with one compiler, but not with another) and in unintended ways. However, code without nested comments will compile as intended, regardless of whether or not the compiler supports nested comments.
There isn't a problem with nesting of "line comments", since the // causes the compiler to ignore everything to end of line. This is okay in C++, since (unlike C) all C++ versions (even pre-standard) support "line comments". (This is not necessarily true if digraphs or trigraphs are used, but MISRA also discourages using them).

Rule 2.2 means C only allows /**/ comments, while rules 2.7.1 tells not to nest C comments, by forbidding the use /* in a C comment. They are unrelated.

C89 had only /* ... */ for comments. But C++ style comments // .. were added to C in C99. I think MISRA simply attempts to keep it consistent so that the C++ style comments do not become an issue if you are compiling the C code in C89/C90.
But this rarely matters anymore as both styles of comments are supported in both modern C and C++.
You can read the MISRA rationale for the reasoning:
MISRA-C-2004 rationale:
Rule 2.3 (required): The character sequence /* shall not be used
within a comment.
C does not support the nesting of comments even though some compilers
support this as a language extension. A comment begins with /*
and continues until the first */ is encountered. Any /* occurring
inside a comment is a violation of this rule.
Consider the following code fragment: /* some comment, end comment
marker accidentally omitted <>
Perform_Critical_Safety_Function(X); /* this comment is not compliant
*/
In reviewing the page containing the call to the function, the
assumption is that it is executed code. Because of the accidental
omission of the end comment marker, the call to the safety
critical function will not be executed.
MISRA-C++ 2008 rationale:
Rule 2-7-1 The character sequence /* shall not be used within a
C-style comment.
C++ does not support the nesting of C-style comments even though some
compilers support this as a non-portable language extension. A comment
beginning with /* continues until the first */ is encountered. Any
/* occurring inside a comment is a violation of this rule.

Although // were an incredibly common non-standard extension to C90 compilers, it was never allowed by the C90 standard. The rationale for the MISRA rule is that you should follow the applicable language standard.
So it's quite simple:
MISRA-C:2004 is for C90 which only allowed /* */ comments.
MISRA-C++:2008 is for C++, which allows // comments (no matter C++ version)
MISRA-C:2012 is for C99 which allows // comments.
Because of the above, the rule you refer to has been removed in MISRA-C:2012. Consider upgrading to the 2012 MISRA version, as it has been improved in many ways.

In short, those standards are to help the programmers from getting inconsistent compiler behaviors due to the comment style when they compile their codes using different compiler standards.
This is the rationale behind the standards.
More elaborated answer:
This is because the // line comment is not supported before C99 standard. While MISRA-C 2004 document is created to support C89/C90 standard.
Rule 2.2 (required): Source code shall only use /* … */ style
comments.
This excludes the use of // C99 style comments and C++ style
comments, since these are not permitted in C90. Many compilers support
the // style of comments as an extension to C90. The use of // in
preprocessor directives (e.g. #define) can vary. Also the mixing of /*
… */ and // is not consistent. This is more than a style issue, since
different (pre C99) compilers may behave differently
Check Lundin's answer on this post. Also, check this SO post on C line commenting before C99.
Thus, that explain why the MISRA-C 2004 clause you post requires /* to be used.
With the same idea, the MISRA-C++ 2008 standard discourages the use of /* - C-Style (multiline) comment - in C++ since some compilers may generate errors. It encourages to use // since it is the "original" C++ comment style.

From MISRA C 2004:
Rule 2.2 (required): Source code shall only use /* … */ style comments.
This excludes the use of // C99 style comments and C++ style comments, since these are not
permitted in C90. Many compilers support the // style of comments as an extension to C90. The
use of // in preprocessor directives (e.g. #define) can vary. Also the mixing of /* … */ and //
is not consistent. This is more than a style issue, since different (pre C99) compilers may behave differently.
I think this explains it all, but I'll still add my explanation with links.
In original C (pre C99), there were no // comments. C++ introduced a double slash comment prefix // as a way to comment single lines.
For more clarity, let's go line by line:
This excludes the use of // C99 style comments and C++ style comments, since these are not
permitted in C90.
Nowadays, modern compilers like gcc have started supporting such // in C90 mode also, but will still issue a warning like:
warning: C++ style comments are not allowed in C90
but it is recommended to use /*..*/ comments in C90 C.
Many compilers support the // style of comments as an extension to C90.
That is what I exactly told above, but it is still not recommended to use // in C90 C as the code will not be portable. For example, that code will compile with gcc, but with another compiler which does not have the extension, it will not compile.
The
use of // in preprocessor directives (e.g. #define) can vary.
I think the meaning of this is clear. It says that the usage of // is not going to be consistent in preprocessor directives.
Also the mixing of /* ... */ and //
is not consistent.
How? This is possible. Like I mentioned above, it varies from compiler to compiler. In C99 C, it will be mostly consistent, but if you're talking about the pre C99 compilers, it matters if they support or not support // comments.
This is more than a style issue, since different (pre C99) compilers may behave differently.
Yes it is. As this is MISRA 2004, which is mainly talking about pre C90 C mainly. This is because most C90 compilers do not support //, and thus you will get an error. If you're using C99, this is invalid.
Questions Expected
Why was there no // in pre C99 C, and then why was it introduced in C++? Is there a specific reason?
C originated from B. B originated from BCPL. // were created during BCPL, and thus BCPl used them. It's successor B started using /*...*/, which were inherited by C. Although, C++ decided to resurrect the BCPL comments, and of course used /*...*/ also. The C-standard at that time took // as a non-standard feature.
When C99 C was introduced, it had the comments //.
What are // and /*...*/ comments called?
// comments are called single-line comments as they can only extend till one line.
/*...*/ comments are called multi-line comments as they can extend upto multiple lines.
Is it compulsory to use only one kind of comment through your source code?
No, you can use any and even both. Although, some people say that using only one type makes the code readable. It is more a matter of opinion.
Is rule 2.2 of MISRA C 2004 outdated?
Kind of. Recently, MISRA 2012 was released which has these changes. Although, if you think that MISRA C 2004 is wrong as it is only concentrating on pre C99, it isn't. I would recommend using MISRA 2012 nowadays.

Rule 2.7.1 (required): The character sequence /* shall not be used with c style comments.
(emphasis added)
I think you are just misreading the meaning of the word "with" in the above rule and interpreting in the sense "shall not be used for c style comments".
Perhaps the rule would be more clear if the word "within" were used rather than "with".

Related

What conditional compilation is needed around C++ attributes?

I'm starting to add [[nodiscard]], [[noreturn]] and [[fallthrough]] to my code base, but I still worry the code might need to be used on an older C++ version.
I'm only worried about g++, clang, and Visual Studio.
To be safe should I make every single usage depend on a version check for the exact version it appeared? Or, do these compilers accept (or does the spec even mandate they accept) any [[attribute]] even if unknown, starting with C++11?
Were these allowed and ignored (or supported) even before C++11? (I ask not what the spec says but what the software actually did.)
#if __cplusplus >= 201703L
#define MyNamespace_NoReturnCPP17 [[noreturn]]
#else
#define MyNamespace_NoReturnCPP17
#endif
(Off subject but if I were on the C++ committee, I'd re-use the case keyword to do the same thing as switch, when followed by (, except it would in effect have an automatic break before each case label. And within the case's block (and nowhere else), fallthrough would be accepted as a keyword, that suppresses that automatic break.)
I note the C++14 spec 7.6.1.5 says behavior is "implemenation-defined" but I'm asking a more practical question about what compilers actually did. https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
The C++17 spec 10.6.1.6 says "Any attribute-token that is not recognized by the implementation is ignored." That answers my question for C++17 and newer, but again my question is about earlier compilers. https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4713.pdf
To be safe should I make every single usage depend on a version check for the exact version it appeared? Or, do these compilers accept (or does the spec even mandate they accept) any [[attribute]] even if unknown, starting with C++11?
I prefer adding version checks for safety although mainstream compilers will throw a warning for unknown attributes.
gcc -Wno-ignored-attributes / -Wattributes
Clang -Wunknown-attributes
MSVC C5030
I'm not sure these warning options(and corresponding behavior) have been added since the first C++11 feature-complete version, so you'd better do some checks.
Were these allowed and ignored (or supported) even before C++11?
Since standard attributes syntax is supported starting from C++11, compilers will have trouble at the parsing stage. Demo

(v) is actually (*&v) since when?

Could C++ standards gurus please enlighten me:
Since which C++ standard version has this statement failed because (v) seems to be equivalent to (*&v)?
I.e. for example the code:
#define DEC(V) ( ((V)>0)? ((V)-=1) : 0 )
...{...
register int v=1;
int r = DEC(v) ;
...}...
This now produces warnings under -std=c++17 like:
cannot take address of register variable
left hand side of operand must be lvalue
Many C macros enclose ALL macro parameters in parentheses, of which the above is meant only to be a representative example.
The actual macros that produce warnings are for instance
the RTA_* macros in /usr/include/linux/rtnetlink.h.
Short of not using/redefining these macros in C++, is there any workaround?
If you look at the revision summary of the latest C++1z draft, you'd see this in [diff.cpp14.dcl.dcl]
[dcl.stc]
Change: Removal of register storage-class-specifier.
Rationale: Enable repurposing of deprecated keyword in future
revisions of this International Standard.
Effect on original feature: A valid C++ 2014 declaration utilizing the register
storage-class-specifier is ill-formed in this International Standard.
The specifier can simply be removed to retain the original meaning.
The warning may be due to that.
register is no longer a storage class specifier, you should remove it. Compilers may not be issuing the right error or warnings but your code should not have register to begin with
The following is a quote from the standard informing people about what they should do with regards to register in their code (relevant part emphasized), you probably have an old version of that file
C.1.6 Clause 10: declarations [diff.dcl]
Change: In C++, register is not a storage class specifier.
Rationale: The storage class specifier had no effect in C++.
Effect on original feature: Deletion of semantically well-defined feature.
Difficulty of converting: Syntactic transformation.
How widely used: Common.
Your worry is unwarranted since the file in question does not actually contain the register keyword:
grep "register" /usr/include/linux/rtnetlink.h
outputs nothing. Either way, you shouldn't be receiving the warning since:
System headers don't emit warnings by default, at least in GCC
It isn't wise to try to compile a file that belongs to a systems project like the linux kernel in C++ mode, as there may be subtle and nasty breaking changes
Just include the file normally or link the C code to your C++ binary. Report a bug if you really are getting a warning that should normally be suppressed to your compiler vendor.

Why are trigraphs generating errors in modern C++ compilers?

Even in the GCC Compilers, the trigraphs are not getting compiled without explicitly specifying the trigraph attribute.
#include<stdio.h>
int main()
{
int a=4;
if((a==4) ??! (a==5))
printf("\nHello world!");
return 0;
}
This program saved as try.c gets compiled in GCC Compiler only when we specify gcc -Wall -trigraphs try.c and it still shows warnings.
Can you enlist some compilers that will treat and handle trigraphs without any errors or warnings?
Trigraphs were introduced by the 1989 ANSI C standard, and are retained in all later C standards (so far; the upcoming C23 standard will drop them). They also appear in the first ISO C++ standard, published in 1998, and in all later C++ standards up to and including C++14. (Trigraphs were removed in C++17. Thanks to Jonathan Leffler and dyp for tracking down the details.)
Quoting a draft of the C++17 standard:
Effect on original feature: Valid C ++ 2014 code that uses trigraphs
may not be valid or may have different semantics in this International
Standard. Implementations may choose to translate trigraphs as
specified in C ++ 2014 if they appear outside of a raw string literal,
as part of the implementation-defined mapping from physical source
file characters to the basic source character set.
They are not an optional feature in either language (prior to C++17); all conforming compilers must support them and interpret them as specified by the respective language standard.
For example, if this program:
#include <stdio.h>
int main(void) {
if ('|' == '??!') {
puts("ok");
}
else {
puts("oops");
}
return 0;
}
prints oops, then your compiler is non-conforming.
But many, perhaps most, C compilers are not fully conforming by default. As long as a compiler can be made to conform to the standard in some way, that's good enough as far as the standard is concerned. (gcc requires -pedantic and -std=... to do this.)
But even if a compiler is fully conforming, there's nothing in the standard that forbids a compiler from warning about anything it likes. A conforming C compiler must diagnose any violation of a syntax rule or constraint, but it can issue as many additional warnings as it likes -- and it needn't distinguish between required diagnostics and other warnings.
Trigraphs are very rarely used. The vast majority of development systems support directly all the characters for which trigraphs substitute: #, [, \, ], ^, {, |, }, ~.
In fact, it's likely that trigraphs are used accidentally more often than they're used correctly:
fprintf(stderr, "What just happened here??!\n");
Warning about trigraphs that might alter the meaning of a program (relative to the meaning it would have if the language didn't have trigraphs) is both permitted by the ISO standard and IMHO perfectly reasonable. Most compilers probably have options to turn off such warnings.
Conversely, for a C++17 compiler that doesn't implement trigraphs, it would be reasonable to warn about sequences that would have been treated as trigraphs in C++14 or earlier, and/or to provide an option to support trigraphs. Again, an option to disable such warnings would be a good thing.
GCC is allergic to trigraphs. You have to explicitly enable them:
gcc -trigraphs ...
The GCC 4.7.1 manual says:
-trigraphs
Support ISO C trigraphs. The -ansi option (and -std options for strict ISO
C conformance) implies -trigraphs.
It also says:
-Wtrigraphs
Warn if any trigraphs are encountered that might change the meaning of the
program (trigraphs within comments are not warned about). This warning is
enabled by -Wall.
They might be turned off by default.
"Some compilers support an option to turn recognition of trigraphs off, or disable trigraphs by default and require an option to turn them on"
GCC might be one of the latter. Although it should by default ignore with warning, but in this case the ignoring might be causing the compile error
Trigraphs are converted at a very early stage of compilation, and can even be replaced in string literals. This makes errors that arise from trigraph translations very hard to detect (worst off if you consider debugging using a log and you find the output in your source).
The warning you see will help you quickly spot a possible culprit to track the source of the bug. Basically it's warning you that something might not be as you think it is.

ISO C++ and the infamous underscore [duplicate]

This MSDN article states that getcwd() has been deprecated and that the ISO C++ compatible _getcwd should be used instead, which raises the question: what makes getcwd() not ISO-compliant?
There is a good discussion about that. P.J. Plauger answers to this
I'm the guy who insisted back in 1983 that the space of
names available to a C program be partitioned into:
a) those defined by the implementation for the benefit of the programmer (such as printf)
b) those reserved to the programmer (such as foo)
c) those reserved to the implementation (such as _unlink)
We knew even then that "the implementation" was too monolithic --
often more than one source supplies bits of the implementation --
but that was the best we could do at the time. Standard C++
has introduced namespaces to help, but they have achieved only
a fraction of their stated goals. (That's what happens when you
standardize a paper tiger.)
In this particular case, Posix supplies a list of category (a) names
(such as unlink) that you should get defined when and only when you
include certain headers. Since the C Standard stole its headers from
Unix, which is the same source as for Posix, some of those headers
overlap historically. Nevertheless, compiler warnings should have
some way of taking into account whether the supported environment
is "pure" Standard C++ (a Platonic ideal) or a mixed C/C++/Posix
environment. The current attempt by Microsoft to help us poor
programmers fails to take that into account. It insists on treating
unlink as a category (b) name, which is myopic.
Well, GCC will not declare POSIX names in strict C mode, at least (though, it still does in C++ mode):
#include <stdio.h>
int main() {
&fdopen;
return 0;
}
Output using -std=c99
test.c: In function 'main':
test.c:4: error: 'fdopen' undeclared (first use in this function)
You will have to tell it explicitly that you are operating in a mixed C/Posix by using feature test macros or not passing any specific standard. It will then default to gnu89 which assumes a mixed environment (man feature_test_macros). Apparently, MSVC does not have that possibility.
Functions not specified in the standard are supposed to be prefixed by an underscore as an indication that they're vendor-specific extensions or adhere to a non-ISO standard. Thus the "compliance" here was for Microsoft to add an underscore to the name of this specific function since it's not part of the ISO standard.
As others have already pointed out, getcwd is not included in ISO C++, but is part of POSIX/IEEE Std 1003.1.
Microsoft has decided to include some of the most commonly used POSIX functions in their C standard library (but prefix these functions with an underscore to essentially discourage their usage).
For the record, getcwd() wasn't deprecated by ISO. It was "deprecated" by Microsoft. Microsoft rewrote many C functions -- often with a little better security in mind (say, string functions that also take a max_length parameter). They then had their compiler spit out these warnings, which I consider bogus because no standards group deprecated any of the functions declared deprecated.
To add on to Dan Olson's post: See ANSI C Compliance page on MSDN
The names of Microsoft-specific functions and global variables begin with a single underscore. These names can be overridden only locally, within the scope of your code. For example, when you include Microsoft run-time header files, you can still locally override the Microsoft-specific function named _open by declaring a local variable of the same name. However, you cannot use this name for your own global function or global variable.
As far as I'm aware getcwd() has never been part of ISO Standard C++. _getcwd() definitely isn't, as standard names will not begin with an underscore.
In fact, the MSDN article links to a man page that says it is declared in direct.h, which is not a Standard C++ header file. The article seems bogus to me.
The MSDN article is somewhat confusing in what a normal person would conclude from just a quick reading (if they don't read it with a very careful lawyer eye).
What the MSDN article says is: getcwd() is not compliant with the ISO C++ standard. To comply with that ISO C++ standard for naming of functions (which is what getcwd violates), Microsoft properly put an _ on the front of the function, so the same function becomes _getcwd(). That is the ISO C++ compliant way of naming the function because getcwd() and _getcwd() are not an ISO C++ standard function, but are a Microsoft (vendor) specific, or implementation specific function.
The article does not indicate what a C++ ISO standard call to get the working directory would be... though thats what folks tend to read at a quick glance.

Why is getcwd() not ISO C++ compliant?

This MSDN article states that getcwd() has been deprecated and that the ISO C++ compatible _getcwd should be used instead, which raises the question: what makes getcwd() not ISO-compliant?
There is a good discussion about that. P.J. Plauger answers to this
I'm the guy who insisted back in 1983 that the space of
names available to a C program be partitioned into:
a) those defined by the implementation for the benefit of the programmer (such as printf)
b) those reserved to the programmer (such as foo)
c) those reserved to the implementation (such as _unlink)
We knew even then that "the implementation" was too monolithic --
often more than one source supplies bits of the implementation --
but that was the best we could do at the time. Standard C++
has introduced namespaces to help, but they have achieved only
a fraction of their stated goals. (That's what happens when you
standardize a paper tiger.)
In this particular case, Posix supplies a list of category (a) names
(such as unlink) that you should get defined when and only when you
include certain headers. Since the C Standard stole its headers from
Unix, which is the same source as for Posix, some of those headers
overlap historically. Nevertheless, compiler warnings should have
some way of taking into account whether the supported environment
is "pure" Standard C++ (a Platonic ideal) or a mixed C/C++/Posix
environment. The current attempt by Microsoft to help us poor
programmers fails to take that into account. It insists on treating
unlink as a category (b) name, which is myopic.
Well, GCC will not declare POSIX names in strict C mode, at least (though, it still does in C++ mode):
#include <stdio.h>
int main() {
&fdopen;
return 0;
}
Output using -std=c99
test.c: In function 'main':
test.c:4: error: 'fdopen' undeclared (first use in this function)
You will have to tell it explicitly that you are operating in a mixed C/Posix by using feature test macros or not passing any specific standard. It will then default to gnu89 which assumes a mixed environment (man feature_test_macros). Apparently, MSVC does not have that possibility.
Functions not specified in the standard are supposed to be prefixed by an underscore as an indication that they're vendor-specific extensions or adhere to a non-ISO standard. Thus the "compliance" here was for Microsoft to add an underscore to the name of this specific function since it's not part of the ISO standard.
As others have already pointed out, getcwd is not included in ISO C++, but is part of POSIX/IEEE Std 1003.1.
Microsoft has decided to include some of the most commonly used POSIX functions in their C standard library (but prefix these functions with an underscore to essentially discourage their usage).
For the record, getcwd() wasn't deprecated by ISO. It was "deprecated" by Microsoft. Microsoft rewrote many C functions -- often with a little better security in mind (say, string functions that also take a max_length parameter). They then had their compiler spit out these warnings, which I consider bogus because no standards group deprecated any of the functions declared deprecated.
To add on to Dan Olson's post: See ANSI C Compliance page on MSDN
The names of Microsoft-specific functions and global variables begin with a single underscore. These names can be overridden only locally, within the scope of your code. For example, when you include Microsoft run-time header files, you can still locally override the Microsoft-specific function named _open by declaring a local variable of the same name. However, you cannot use this name for your own global function or global variable.
As far as I'm aware getcwd() has never been part of ISO Standard C++. _getcwd() definitely isn't, as standard names will not begin with an underscore.
In fact, the MSDN article links to a man page that says it is declared in direct.h, which is not a Standard C++ header file. The article seems bogus to me.
The MSDN article is somewhat confusing in what a normal person would conclude from just a quick reading (if they don't read it with a very careful lawyer eye).
What the MSDN article says is: getcwd() is not compliant with the ISO C++ standard. To comply with that ISO C++ standard for naming of functions (which is what getcwd violates), Microsoft properly put an _ on the front of the function, so the same function becomes _getcwd(). That is the ISO C++ compliant way of naming the function because getcwd() and _getcwd() are not an ISO C++ standard function, but are a Microsoft (vendor) specific, or implementation specific function.
The article does not indicate what a C++ ISO standard call to get the working directory would be... though thats what folks tend to read at a quick glance.