how to recognize whether code is C or C++?

K

Keith Thompson

S Claus said:
here is a question, just out of curiousity:

If you are given a bunch of .c files, is there a way to recognize (by
just looking at them) whether the code in them is written in C or in C+
+?

What would you look for?

There is no reliable algorithm for doing this. For one thing, the
same source file might be valid both as C and as C++, either because
it doesn't happen to use any of the unique features of either language
or because it was deliberately designed to be compatible, perhaps by
using #ifdef __cplusplus". And a lot of C code is valid C++ anyway,
though probably not idiomatic C++.

And a sufficiently perverse programmer might write code that's
intended to look like one language when it's not:

cout << x << '\n';

looks like C++ until you realize that cout is declared as an unsigned
int. (Which is still valid C++.)

Note that // comments don't distinguish between C and C++; C99 allows
them, and many pre-C99 compilers support them as an extension.

Most of the things I'd look for have already been mentioned:

Standard header names ::
new, delete
 
B

Bart van Ingen Schenau

Noah said:
Bart said:
Noah said:
James Kanze wrote:

But there's no argument, since the compiler doesn't care.
That IS the argument. Human says it matters, compiler says it
doesn't.
Compiler wins. How does it win? Because you'll find it provides
no
indication you're using struct/class in a manner that violates
whatever
distinction you have made up. A 'struct' that has "become" a
'class' can slip by the compiler with no warning whatsoever.

By that reasoning, this is perfect code, because the compiler accepts
it:

#include<stdio.h>
int main(int,const char**v){goto L8;L2:return 99;L3:if((*v)[0])goto
L6;else goto L2;L4:v[0]++;L5:goto L3;L6:putchar(**v);goto
L4;L8:v[0]="hello, world\n";goto L5;}

It compiles cleanly and works as expected, so there can not be any
hindrance in putting this code in the production archive. Or is
there?

I'll clue you into the difference.

The above is pretty much illegible. However, the scope of the problem
is rather limited. If there are functions elsewhere that have
adequate
formatting,

Why do you assume code to have different formatting than the function I
presented above? Formatting (and variable naming) don't convey any more
meaning to the compiler than the difference between class and struct
(which you insist is non-existent).

Rules about writing readable code are just pointless standards, because
the compiler can't enforce them.

Claiming that apples should all be red because oranges are orange is
not convincing.

Claiming you can not differentiate between red apples and green apples,
because they are all apples is equally non-convincing.

As I see it, attaching additional meaning to class or struct is a style
issue, similar to naming conventions and brace placement.
There is no absolute right or wrong, but it helps if you follow the
local conventions.

Bart v Ingen Schenau
 
B

Bart van Ingen Schenau

Keith said:
Maybe. Or maybe there was a legitimate reason. Perhaps the code was
subtly incompatible with C++ in some way, and using "class" as an
identifier prevents someone from accidentally using it from C++.

(I'm not saying it's likely, but it's conceivable.)

If the header is truly incompatible with C++, I would have used a much
stronger signal to indicate that. Something like
#ifdef __cplusplus
#error This header can't be used in C++ code
#endif
It's like when designing a door to your house: even if you and your
wife are both short people (short people, short people! :)[1]) you
design that door so that other people can just walk in without
risking banging their head.

Or, I would, if I were that short and were designing a door.

Ah, but if you don't like tall people ...
Then you would design a door that looks too small for those tall people.
You would not paint a large door around your small one to fool those
large people (unless you were malicious, but then you would also hang up
a sign saying 'tall people welcome').

Bart v Ingen Schenau
 
N

Noah Roberts

Bart said:
Noah said:
Bart van Ingen Schenau wrote:
#include<stdio.h>
int main(int,const char**v){goto L8;L2:return 99;L3:if((*v)[0])goto
L6;else goto L2;L4:v[0]++;L5:goto L3;L6:putchar(**v);goto
L4;L8:v[0]="hello, world\n";goto L5;}

It compiles cleanly and works as expected, so there can not be any
hindrance in putting this code in the production archive. Or is
there?
I'll clue you into the difference.

The above is pretty much illegible. However, the scope of the problem
is rather limited. If there are functions elsewhere that have
adequate
formatting,

Why do you assume code to have different formatting than the function I
presented above? Formatting (and variable naming) don't convey any more
meaning to the compiler than the difference between class and struct
(which you insist is non-existent).

Sigh. I was attempting to explain the difference between something
meant to convey communication as you read it, and something meant to
convey communication in some separate area of code. Any formatting
problem with main is a problem right there, not somewhere else. Using
the struct keyword to communicate PODhood or some other thing that has
wide reaching meaning is not sufficient toward that end because the call
site does not have that information anywhere.
Rules about writing readable code are just pointless standards, because
the compiler can't enforce them.

Wrong, but go ahead and feel that way. However, rules about
"readability" that have nothing to do with readability, do not help with
readability, and can be broken too easily without any warning...that
require editing the project in multiple locations in order to keep up
with this "readability", are more than just pointless...they're stupid.
Claiming you can not differentiate between red apples and green apples,
because they are all apples is equally non-convincing.

As I see it, attaching additional meaning to class or struct is a style
issue, similar to naming conventions and brace placement.

There are several differences. Naming conventions follow objects
around. A naming convention is at any site that the object is used.
Not so with declaration keywords. If you're going to insist that
PODness needs to be communicated to users, then use your naming
conventions to dictate that; call pods podObject or something.

No, I wouldn't recommend that. Names should indicate purpose, not type.
But hey, everyone wants to know if this thing's a POD or not and want
that indicated in the type somehow even if it really isn't.

Brace placement is also a stupid thing to argue about but at least it is
less so than using 'struct' to carry meaning it isn't meant to carry.
It at least affects local code structure and readability.
There is no absolute right or wrong, but it helps if you follow the
local conventions.

I never said there was an absolute right or wrong. I suggested that the
idea of forcing yourself to use class instead of struct was uncalled for
and this seems to have ruffled many feathers, including yours.
 
B

Bart van Ingen Schenau

Noah said:
Sigh. I was attempting to explain the difference between something
meant to convey communication as you read it, and something meant to
convey communication in some separate area of code. Any formatting
problem with main is a problem right there, not somewhere else. Using
the struct keyword to communicate PODhood or some other thing that has
wide reaching meaning is not sufficient toward that end because the
call site does not have that information anywhere.

It seems we are talking at slight cross-angles, because I agree that
communication PODness by using struct is a failed strategy.

What I try to communicate when using struct is one of two things
1. The code must be usable in both C and C++
2. The type has no class-invariant and is regarded as a loose
aggregation of members. Direct access to the data members (without using
an accessor function) is explicitly allowed. There are no further
restrictions on the type (so having a non-POD member, a constructor, a
member function, etc. is no problem).

Which of the two cases holds for the structure follows from the
documentation.
In the second case, the struct keyword is meant to serve as a reminder,
first to the maintainer that fiddling with the data members constitutes
an interface change and that adding a class-invariant requires updating
all the clients. And secondly to the clients that the public access on
the data members is intentional and that you can directly access them.

As you can see, the struct keyword as wide reaching effects, but the
place where it matters most is in close proximity to where the keyword
appears in the code.
Wrong, but go ahead and feel that way. However, rules about
"readability" that have nothing to do with readability, do not help
with
readability, and can be broken too easily without any warning...that
require editing the project in multiple locations in order to keep up
with this "readability", are more than just pointless...they're
stupid.

I agree. That is why my 'rules' about usage of the struct keyword are
not about readability. They are about the contract between the
author/maintainer of the class or struct and their users and are
primarily meant as a quick visual reminder to the maintainer that
something special is going on.

Bart v Ingen Schenau
 
N

Noah Roberts

Bart said:
What I try to communicate when using struct is one of two things
1. The code must be usable in both C and C++

Admittedly, I couldn't care less about compatibility with C.
2. The type has no class-invariant and is regarded as a loose
aggregation of members. Direct access to the data members (without using
an accessor function) is explicitly allowed.

Interesting. I've felt no need to use anything but access permission
keywords to express access permission. IMHO, using access permission
keywords to express access permission is the better approach since it is
the method directly supported by the language in addition to expressing
exactly what you want to express.
Which of the two cases holds for the structure follows from the
documentation.
In the second case, the struct keyword is meant to serve as a reminder,
first to the maintainer that fiddling with the data members constitutes
an interface change and that adding a class-invariant requires updating
all the clients. And secondly to the clients that the public access on
the data members is intentional and that you can directly access them.

I suppose if you don't already follow the principle that direct public
access to internal values is a bad thing, you might need to find ways to
communicate when you adamantly want to maintain it.

As to the assertion that the public access on data members is
intentional, that just might be a good argument for using the 'class'
keyword for these cases since it would *require* the author to write
'public:' in order to explicitly state public access...in a 'struct'
they can forget and the maintainer can't be sure if they did or not
(unless they are intimately familiar with your alteration of the
semantics of other keywords in the language).
 
B

Bart van Ingen Schenau

Noah said:
Admittedly, I couldn't care less about compatibility with C.


Interesting. I've felt no need to use anything but access permission
keywords to express access permission. IMHO, using access permission
keywords to express access permission is the better approach since it
is the method directly supported by the language in addition to
expressing exactly what you want to express.

Well, using struct and access specifiers is not an either/or
proposition, but and/and.

The struct keyword signals that the type deviates from the established
best practices (for that project). Giving public access to member
variables is just the most common deviation.
I suppose if you don't already follow the principle that direct public
access to internal values is a bad thing, you might need to find ways
to communicate when you adamantly want to maintain it.

As to the assertion that the public access on data members is
intentional, that just might be a good argument for using the 'class'
keyword for these cases since it would *require* the author to write
'public:' in order to explicitly state public access...in a 'struct'
they can forget and the maintainer can't be sure if they did or not
(unless they are intimately familiar with your alteration of the
semantics of other keywords in the language).

When people are in the habit of writing
class X {
public:
// public members
private:
// private members
};

then by leaving out the access specifier 'private', it becomes obscured
if the public access to the data members was intentional or an oversight
in adding the correct access specifier.
You may argue that the private members should be listed first, but in my
experience that is simply not how classes are written.

And before a maintainer even dares to touch the code, he/she should be
familiar with the relevant project documentation, which includes the
coding guidelines where the convention for using class or struct is
explained.

Bart v Ingen Schenau
 
N

Noah Roberts

Bart said:
Well, using struct and access specifiers is not an either/or
proposition, but and/and.

The struct keyword signals that the type deviates from the established
best practices (for that project). Giving public access to member
variables is just the most common deviation.
....

And before a maintainer even dares to touch the code, he/she should be
familiar with the relevant project documentation, which includes the
coding guidelines where the convention for using class or struct is
explained.

I can't help but notice that everyone's argument for using struct to
signal some meaning it doesn't have always ends up coming back to some
existing practice or documentation that already assumes the conclusion.
A circular argument through authority so to speak.

I'm not arguing that one ignores guidelines that someone decided to put
in a project. I'm arguing that when you're in charge of making
guidelines you don't put such a meaningless and easily broken one in
your guidelines. I'm arguing that it makes no sense, *inherently*, to
do so.
 
B

Bart van Ingen Schenau

Noah said:
I can't help but notice that everyone's argument for using struct to
signal some meaning it doesn't have always ends up coming back to some
existing practice or documentation that already assumes the
conclusion.
A circular argument through authority so to speak.

I'm not arguing that one ignores guidelines that someone decided to
put
in a project. I'm arguing that when you're in charge of making
guidelines you don't put such a meaningless and easily broken one in
your guidelines. I'm arguing that it makes no sense, *inherently*, to
do so.

I can't help but notice that you advocate a 'free for all' coding
attitude where only the compiler is the final arbiter on what is
acceptable and what not.

The entire reason for having coding guidelines at all is to document
those conventions that can NOT be checked by the compiler and are hence
easily broken.

We started this exchange with this program (reformatted):

#include<stdio.h>
int main(int, const char**v)
{
goto L8;
L2: return 99;
L3: if((*v)[0])
goto L6;
else
goto L2;
L4: v[0]++;
L5: goto L3;
L6: putchar(**v);
goto L4;
L8: v[0]="hello, world\n";
goto L5;
}

I would agree with you that this code is hopelessly unmaintainable, but
maintainability is too subjective a term to be able to use it in rooting
out bad code.
To keep bad code out of your project, you need some restrictions and
conventions on how the C++ language can be used within the project that
go beyond what a compiler is required to diagnose.

Your argument against assigning a restricted meaning to struct is that
the compiler can't help you in enforcing that restricted meaning.
My counter-argument is that with such an attitude, you also can not in a
meaningful manner impose a naming convention or restrict the use of
dangerous/unmaintainable constructs (like goto).

This does not mean that you *must* follow all these guidelines, just
that if you want to follow one of them, your argument why struct can't
have a restricted meaning falls down. An argument like "I don't like
such a rule in my project" would still be valid not to implement it in
your guidelines.
And don't come with the local vs remote effect argument, because that
would only prove you have not been paying attention.

Bart v Ingen Schenau
 
N

Noah Roberts

Bart said:
Your argument against assigning a restricted meaning to struct is that
the compiler can't help you in enforcing that restricted meaning.

Again, you misrepresent my argument. It seems on purpose since I quite
explained it earlier.

It's too hard to track what everyone whats to use this struct keyword
for. It seems that among the various proponents for using struct only
for some something or other, but never classes, can't agree on what that
something or other is. This speaks volumes toward its utility in
expressing any one of these things.

The point of my argument is that 'struct' and 'class' mean exactly the
same thing in the C++ language. There is no inherent reason to prefer
'class' over 'struct'. The various purposes proposed range from
ill-defined to overly strict and difficult to enforce. Since you'll get
no help from the compiler, and the things you want to enforce need to be
tracked by the individual in ways that have nothing to do with 'struct'
vs. 'class', the use of these keywords to hold extra meaning seems to be
quite ill-advised.

You're taking this statement and inverting it incorrectly. Just because
THIS non-compiler enforced semantic issue is ill-advised does not mean
that ALL are. I gave quite concrete reasons why I think attempting to
force people to use 'struct' only for "non-class" objects is
questionable at best, and why those same arguments can't be applied to
code formatting and standards in general.

You say you want C compatibility, but this does not preclude not using
struct for classes.

You say you want to ensure this or that, but this does not preclude not
using struct for classes.

All the various purported reasons given so far seem to me to be better
expressed in comments. "This object needs to be C compatible," for
instance (which might also be expressed with extern "C"). The 'struct'
keyword does not seem sufficient to express what is desired in any of
these cases, nobody agrees what it should be expressing, and the use of
'struct' in modern C++ texts for objects that could certainly be viewed
as class-like in nature is quickly becoming common.

The OP stated, as point of fact, that you should never use 'struct' for
class objects and I stand utterly unconvinced so far that this is a
logical assumption. Frankly, the best argument for using 'class'
instead of struct is to force the very verbosity that the OP was
complaining about originally. I haven't seen a need to issue such a
constraint in my team.

I'm not saying that coding standards are useless (we have many), just
this one. No amount of misrepresenting of that argument will change it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,159
Messages
2,570,888
Members
47,420
Latest member
ZitaVos505

Latest Threads

Top