Am I being too C++ like?

N

nroberts

I'm working on a C project and I come from C++ background. I used to
work with C 10 years ago though when I was first learning various
languages and used things like Xlib, Xt, etc...

I keep getting told that what I write is more C++ like. I find it odd
because I'm actually using C keywords I rarely if ever use in C++ like
union. But two main examples come to mind:

First, I use opaque types to encapsulate data so I can depend on the
integrity of my structures. For example, when making a stack I had a
header like so:

struct stack;
typedef struct stack Stack;

Stack* createList();
void* popFront(Stack*);
void pushBack(Stack*);

etc...

Another example is when I'm parsing an unknown string into one of
several possibilities:

typedef struct base
{
int type;
// shared data among all valid inputs
} Base;

typedef struct variant_a
{
Base base;
// particular data members
} VariantA;

.... more variants...

typedef union blob
{
int type;
Base base;
VariantA a;
...etc...
} Blob;

Blob * parse(char const*);

I've seen both of these used a lot in various C projects, but has it
gone out of style or something? I suppose it's kind of OOesque, but
I've always thought of that as one paradigm for use in any
language...not something unique to any particular one. Is that an
unpopular conception? If I were to do something similar in C++ it
would look absolutely nothing like the above...why do people think
it's C++ like? Are they full of it or am I? Both? Neither?
 
S

Shao Miller

I'm working on a C project and I come from C++ background. I used to
work with C 10 years ago though when I was first learning various
languages and used things like Xlib, Xt, etc...

I keep getting told that what I write is more C++ like. I find it odd
because I'm actually using C keywords I rarely if ever use in C++ like
union. But two main examples come to mind:

If you're typing legitimate C, then perhaps they're merely thinking of
style.
First, I use opaque types to encapsulate data so I can depend on the
integrity of my structures. For example, when making a stack I had a
header like so:

struct stack;
typedef struct stack Stack;

Stack* createList();
void* popFront(Stack*);
void pushBack(Stack*);

etc...

Some notes about the above...

You've got an interesting mix of styles with your 'struct' tag and
'typedef' type. In C code that I've seen, it's more common to have:

struct stack;
typedef struct stack stack;

Or:

struct stack;
typedef struct stack stack_t;

In my own current, personal preference (which is not reflective of any C
community that I'm aware of), when I do not wish anyone to use the
'struct' keyword, I type something like:

struct s_stack_;
typedef struct s_stack_ s_stack;
/* ... */
struct s_stack_ {
...
};
/* We'll never see 's_stack_' again */

Or if people might or might not care to use the 'struct' keyword is:

struct stack;
typedef struct stack s_stack;
/* ... */
struct stack {
...
};
/* ... */
/* People can do */
struct stack foo;
/* Or they can do */
s_stack bar;

You're using the so-called "Pascal Case" for the 'typedef' type. This
might not be un-C-like, but I've seen more C++ code with this style than
I have seen C code with it.

You're using the so-called "Camel Case" for the functions' identifiers.
This might not be un-C-like, but I've seen more C++ code with this
style than I have seen C code with it.

"When In Rome..." I think it's good to follow any established style
guidelines that might exist for a project. If it's completely up to
you, please just be consistent. :)

If you don't specifically require an empty parameter list, please use
'void' inside your function declarations for functions having no parameters.

Stack * create_list(void);
Another example is when I'm parsing an unknown string into one of
several possibilities:

typedef struct base
{
int type;
// shared data among all valid inputs
} Base;

Call me old-fashioned, but '//' comments always strike me as C++-like,
though they've been in Standard C since C99. They're extremely common
and people report them to be quite handy.
typedef struct variant_a
{
Base base;
// particular data members
} VariantA;

Something about 'xxx_yyy_zzz' strikes me as C-like and something about
'XxxYyyZzz' strikes me as C++-like. The cause for this association
probably amounts to little more than the introductory books' examples
for these languages, when I first read them. It's a pretty trivial
association.
... more variants...

typedef union blob
{
int type;
Base base;
VariantA a;
...etc...
} Blob;

Blob * parse(char const*);

I've seen both of these used a lot in various C projects, but has it
gone out of style or something? I suppose it's kind of OOesque, but
I've always thought of that as one paradigm for use in any
language...not something unique to any particular one. Is that an
unpopular conception? If I were to do something similar in C++ it
would look absolutely nothing like the above...why do people think
it's C++ like? Are they full of it or am I? Both? Neither?

"Are they...?" They are. If you want to strive for "C-like," you could
study all of the code examples in a C Standard and try to pick out
patterns. Then again, that might just be reflective of those authors'
preferences! ;)

- Shao Miller
 
N

Nobody

Call me old-fashioned, but '//' comments always strike me as C++-like,
though they've been in Standard C since C99. They're extremely common
and people report them to be quite handy.

OTOH, they really shouldn't be used in "public" headers unless those
headers would otherwise require C99 support, as it (gratuitously)
precludes using -std=c89 for compiling any code which uses those headers.
 
P

Philip Lantz

nroberts said:
I keep getting told that what I write is more C++ like. I find it odd
because I'm actually using C keywords I rarely if ever use in C++ like
union.

Do they mean this as a criticism, or simply as an observation?

Maybe you should just consider it a compliment and move on...
 
M

Malcolm McLean

I keep getting told that what I write is more C++ like.  I find it odd
because I'm actually using C keywords I rarely if ever use in C++ like
union.  But two main examples come to mind:

First, I use opaque types to encapsulate data so I can depend on the
integrity of my structures.  For example, when making a stack I had a
header like so:

struct stack;
typedef struct stack Stack;

Stack* createList();
void* popFront(Stack*);
void pushBack(Stack*);
In C, it's normal to hardcode simple structures like stacks. It's not
clear to me whether this is a strong point or a weak point of the
language, but it's generally easier to create a stack and stacktop
index with whatever structure you're pushing and popping than to mess
about with generic stack types. On feature is that your expression
parser, or whatever it is you are using the stack for, does not have a
dependency on a stack module.
typedef struct base
{
  int type;
  // shared data among all valid inputs

} Base;
This is C++ implemented in C. Effectively what you are doing is
writing your own set of conventions for handling polymorphic data
types, and implementing them in C. Which means that C isn't the right
language for this approach. Sometimes it's necessary to use the wrong
language because of other considerations. However it should be a last
resort, and done sparingly.
 
J

Jorgen Grahn

I'm working on a C project and I come from C++ background. I used to
work with C 10 years ago though when I was first learning various
languages and used things like Xlib, Xt, etc...

I keep getting told that what I write is more C++ like. I find it odd
because I'm actually using C keywords I rarely if ever use in C++ like
union. But two main examples come to mind:

First, I use opaque types to encapsulate data so I can depend on the
integrity of my structures. For example, when making a stack I had a
header like so:

struct stack;
typedef struct stack Stack;

Stack* createList(); ^
void

void* popFront(Stack*);
void pushBack(Stack*);

I'd skip the typedef -- if something is a struct, I want to see
that immediately. People typedef the weirdest things, so I feel I
cannot assume such a name is a struct, and not a pointer or something.

And I wouldn't hide the contents of struct Stack unless I had specific
reasons.

I'm doing it now in a piece of code I'm refactoring, but it's
because the interpretation of the contents of my struct has been a
source of bugs and confusion in the past. Now you can't get at it
except through a few well-defined and documented functions.

If you do it /everywhere/ it looks odd to me, especially the
createStack() which implies malloc()ed memory which you always have to
remember to handle manually. I'm usually not willing to pay that price.
Another example is when I'm parsing an unknown string into one of
several possibilities:
....

I've seen both of these used a lot in various C projects, but has it
gone out of style or something? I suppose it's kind of OOesque, but
I've always thought of that as one paradigm for use in any
language...not something unique to any particular one.

For what it's worth, the Foo_function(struct Foo*, int arg) idiom
is something I used for years before I learned C++. But most C code I
see uses no particular idiom ... unless 'ad hoc' is one.

/Jorgen
 
R

Rui Maciel

Malcolm said:
In C, it's normal to hardcode simple structures like stacks. It's not
clear to me whether this is a strong point or a weak point of the
language, but it's generally easier to create a stack and stacktop
index with whatever structure you're pushing and popping than to mess
about with generic stack types.

I believe it is a point where C is considerably weak. Better yet, it's a
point where the C programming language could improve a great deal. If the C
programming language supported function templates, even without supporting
any form of template metaprogramming or non-type parameters, trully generic
data structures would be possible without resorting to any coding voodoo.
And this would be a good thing.

Then again, if someone really requires templates and generic data structures
then there is always C++.


Rui Maciel
 
R

Rui Maciel

nroberts said:
I'm working on a C project and I come from C++ background. I used to
work with C 10 years ago though when I was first learning various
languages and used things like Xlib, Xt, etc...

I keep getting told that what I write is more C++ like. I find it odd
because I'm actually using C keywords I rarely if ever use in C++ like
union. But two main examples come to mind:
<snip/>

From your description, it appears you tend to employ OO tricks in your code,
mainly encapsulation and inheritance. That isn't necessarily the "C++ like"
way of doing things, only the application of some principles associated with
a particular programing paradigm.

From this, I agree with you. It is a paradigm, not something unique to any
particular programming language. Maybe some people see it as being
something related to C++, as they associate OO with C++. Yet, C++ isn't the
OO paradigm, and OO paradigm isn't the C++ programming language, nor Java or
any other one.

So, in the end the only question that I believe is relevant in this case is:
does it matter? More specifically, are these OO tricks responsible for any
problem? If they don't then why bother with them?


Rui Maciel
 
B

BartC

I'd skip the typedef -- if something is a struct, I want to see
that immediately. People typedef the weirdest things, so I feel I
cannot assume such a name is a struct, and not a pointer or something.

Couldn't you make exactly the same argument for *anything* defined with
typedef?
 
I

ImpalerCore

If you're typing legitimate C, then perhaps they're merely thinking of
style.





Some notes about the above...

You've got an interesting mix of styles with your 'struct' tag and
'typedef' type.  In C code that I've seen, it's more common to have:

   struct stack;
   typedef struct stack stack;

Or:

   struct stack;
   typedef struct stack stack_t;

In my own current, personal preference (which is not reflective of any C
community that I'm aware of), when I do not wish anyone to use the
'struct' keyword, I type something like:

   struct s_stack_;
   typedef struct s_stack_ s_stack;
   /* ... */
   struct s_stack_ {
       ...
     };
   /* We'll never see 's_stack_' again */

Or if people might or might not care to use the 'struct' keyword is:

   struct stack;
   typedef struct stack s_stack;
   /* ... */
   struct stack {
       ...
     };
   /* ... */
   /* People can do */
   struct stack foo;
   /* Or they can do */
   s_stack bar;

My preference in the code that I write is to cater to both crowds with
a preprocessor symbol.

\code snippet
struct c_stack
{
...
};

#if defined(C_ALIAS_TYPES)
/*! \brief Alias the <tt>struct c_stack</tt> type. */
typedef struct c_stack c_stack;
#endif
\endcode

All the library code is written using the 'struct c_stack' style, but
the documentation examples may define C_ALIAS_TYPES in its Makefile to
make the example code less verbose. The preprocessor symbol doesn't
have any granularity for those that want to mix and match type usage.
You're using the so-called "Pascal Case" for the 'typedef' type.  This
might not be un-C-like, but I've seen more C++ code with this style than
I have seen C code with it.

You're using the so-called "Camel Case" for the functions' identifiers.
  This might not be un-C-like, but I've seen more C++ code with this
style than I have seen C code with it.

I have seen this when the interface is designed before the language is
chosen. For example, the XML DOM specification is written in OMG
IDL. If one were to write a C language binding, is it better to
following the naming convention of the standard, or a naming
convention more commonplace to the language?
"When In Rome..." I think it's good to follow any established style
guidelines that might exist for a project.  If it's completely up to
you, please just be consistent. :)
Yep.

If you don't specifically require an empty parameter list, please use
'void' inside your function declarations for functions having no parameters.

   Stack * create_list(void);



Call me old-fashioned, but '//' comments always strike me as C++-like,
though they've been in Standard C since C99.  They're extremely common
and people report them to be quite handy.

They can be particularly handy in Doxygen documentation when writing
literal C examples because writing */ in a Doxygen C code sample will
make things go awry.

\code
/*!
* \brief Something useful.
* \param arg1
* \param arg2
* \return blah blah
* ...
*
* Usage:
*
* \code
* int main(void)
* {
* // These style of comments are a necessity, unless you put the
* // example in its own file and include it using '\include'.
* useful_function( arg1, arg2 );
*
* return 0;
* }
*/
\endcode
Something about 'xxx_yyy_zzz' strikes me as C-like and something about
'XxxYyyZzz' strikes me as C++-like.  The cause for this association
probably amounts to little more than the introductory books' examples
for these languages, when I first read them.  It's a pretty trivial
association.





"Are they...?"  They are.  If you want to strive for "C-like," you could
study all of the code examples in a C Standard and try to pick out
patterns.  Then again, that might just be reflective of those authors'
preferences! ;)

Yep, the inertia of a project (and its people) should be considered
before attempting to alter its trajectory. The question is, how much
mass do you have?

Best regards,
John D.
 
J

Joe keane

I've seen both of these used a lot in various C projects, but has it
gone out of style or something?

It's just good programming.

Good C code resembles C++ written in C.
Bad C code resembles fettucine alfredo.
 
K

Keith Thompson

BartC said:
Couldn't you make exactly the same argument for *anything* defined with
typedef?

Not quite.

A typedef for a struct type just creates a new name (like "foo") for
something that already has a name (like "struct foo"). It typically
provides no new information, nor does it hide information that
should be hidden; usually the code that refers to the type already
depends on the fact that it's a struct. (For a truly opaque type,
a typedef makes sense; the standard FILE is an example.)

On the other hand, a typedef for a numeric type is typically
parameterized, and may refer to different types depending on
the platform. Examples from the standard library include size_t
and ptrdiff_t.

Typedefs can also be useful for types that might be overly complex
to write out; for example:

typedef void (*signal_handler)(int);
 
I

Ian Collins

I'm working on a C project and I come from C++ background. I used to
work with C 10 years ago though when I was first learning various
languages and used things like Xlib, Xt, etc...

If you had used XView, you wouldn't be asking this question! XView was
my introduction to OO programming in C.
I keep getting told that what I write is more C++ like. I find it odd
because I'm actually using C keywords I rarely if ever use in C++ like
union. But two main examples come to mind:

First, I use opaque types to encapsulate data so I can depend on the
integrity of my structures. For example, when making a stack I had a
header like so:

struct stack;
typedef struct stack Stack;

Stack* createList();
void* popFront(Stack*);
void pushBack(Stack*);

etc...

Another example is when I'm parsing an unknown string into one of
several possibilities:

typedef struct base
{
int type;
// shared data among all valid inputs
} Base;

typedef struct variant_a
{
Base base;
// particular data members
} VariantA;

.... more variants...

typedef union blob
{
int type;
Base base;
VariantA a;
...etc...
} Blob;

Blob * parse(char const*);

I've seen both of these used a lot in various C projects, but has it
gone out of style or something? I suppose it's kind of OOesque, but
I've always thought of that as one paradigm for use in any
language...not something unique to any particular one. Is that an
unpopular conception? If I were to do something similar in C++ it
would look absolutely nothing like the above...why do people think
it's C++ like? Are they full of it or am I? Both? Neither?

You are correct, what you are writing is OO C, not C++ like C. If it
passes its tests and your colleagues understand it, go for it.
 
B

BartC

Keith Thompson said:
Not quite.

A typedef for a struct type just creates a new name (like "foo") for
something that already has a name (like "struct foo"). It typically
provides no new information, nor does it hide information that
should be hidden;

But if I create a new typedef T, and then declare:

T a;

I can't see at a glance whether T is a number, struct, and anything else.
That seemed to be the point of JG's remark. In this case it *does* hide some
information.
 
M

Malcolm McLean

You are correct, what you are writing is OO C, not C++ like C.  If it
passes its tests and your colleagues understand it, go for it.
OO C is C++-like C.

C++ provides support for object-orientation, C doesn't. Of course
ultimately a design paradigm is independent of the language used to
implement it, and you can emulate any language wtih any other (hence
the claim sometimes made that every sufficiently large project
contains a bug-ridden and informally specified implementation of
Lisp). But it's a lot easier to use languages for the purposes for
which they are intended.
 
E

Eric Sosman

But if I create a new typedef T, and then declare:

T a;

I can't see at a glance whether T is a number, struct, and anything
else. That seemed to be the point of JG's remark. In this case it *does*
hide some information.

Not very effectively, since you need to rediscover at least
some of the "hidden" information before you can use `a'.

a = 42; // legal?
*a |= 42; // legal?
a.fizz = 42; // legal?
a->buzz = 42; // legal?
puts(a); // legal?
longjmp(a, 42); // legal?
a(42); // legal?

As a matter of personal taste I rather like typedef aliases
for struct types (and less often, union types), and I intensely
dislike them for data pointer types (but sometimes use them for
function pointers). For scalar types, I use typedef not so much
for opacity but for portability, using <limits.h> and #if to find
a type with suitable range and publishing the result as a typedef
name. But these are just my preferences, not binding on anyone
and not enshrined in a style standard.
 
M

Malcolm McLean

As a matter of personal taste I rather like typedef aliases
for struct types (and less often, union types), and I intensely
dislike them for data pointer types (but sometimes use them for
function pointers).
Say we want an array of ten function pointers that return int and take
a void *.

the syntax is

int (*myftable[10])(void *ptr);

that's really too difficult.

typedef int (*myfpointer)(void *ptr);

myfpointer myftable[10];

is a lot easier to understand.
 
I

Ian Collins

OO C is C++-like C.

No, it's OO C. OO C was around before we had C++.
C++ provides support for object-orientation, C doesn't. Of course
ultimately a design paradigm is independent of the language used to
implement it, and you can emulate any language wtih any other (hence
the claim sometimes made that every sufficiently large project
contains a bug-ridden and informally specified implementation of
Lisp). But it's a lot easier to use languages for the purposes for
which they are intended.

The key point is because of a lack of language support, OO C doesn't
look like C++. The question could have been "Am I being too Java like?"
 
K

Keith Thompson

Eric Sosman said:
As a matter of personal taste I rather like typedef aliases
for struct types (and less often, union types), and I intensely
dislike them for data pointer types (but sometimes use them for
function pointers).

[...]

You could typedef the function type itself rather than the
pointer-to-function type:

typedef void signal_handler(int);
 
K

Kleuske

On 1/20/2012 8:44 AM, BartC wrote:


Not very effectively, since you need to rediscover at least
some of the "hidden" information before you can use `a'.

a = 42; // legal?
*a |= 42; // legal?
a.fizz = 42; // legal?
a->buzz = 42; // legal?
puts(a); // legal?
longjmp(a, 42); // legal?
a(42); // legal?

As a matter of personal taste I rather like typedef aliases
for struct types (and less often, union types), and I intensely dislike
them for data pointer types (but sometimes use them for function
pointers). For scalar types, I use typedef not so much for opacity but
for portability, using <limits.h> and #if to find a type with suitable
range and publishing the result as a typedef name. But these are just
my preferences, not binding on anyone and not enshrined in a style
standard.

In many cases a well_chosen name can actually _add_ some information. Consider
something like:

typedef unsigned int ipaddr_t;

and speculate what variables of this type are used for.

PS. Target platform allows the assumption sizeof(unsigned int)==4.
 

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

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top