C/C++ guidelines

C

Charlie Gordon

Harald van D?k said:
If you would like a helper function such as:

static inline int *alloc_int(void) {
return malloc(sizeof(int));
}

but are implementing it as a macro:

#define alloc_int() malloc(sizeof(int))

not casting the result means you can assign it to a float * without any
diagnostic. I will admit that this is not a very common case though.

Types allocation macros can help make code more readable, without casts, yet
detect some mismatches.:

#include <stdlib.h>
#define alloc_type(type) ((type*)malloc(sizeof(type)))
#define alloc_array(type,n) ((type*)malloc((n) * sizeof(type)))

char *p = alloc_array(char, 100);
int *p = alloc_array(int, 100);
float *p = alloc_array(int, 100); // constraint violation
 
S

Szabolcs Nagy

Richard said:
Keith Thompson said:

That's a contradiction in terms.

why?

imho many people would use a well designed portable c99 lib that
covers most of the basic things (which are not so basic to be in the
stdlib) a la boost

at least it would be good for educational reasons (how to write nice
c99 code)

i don't know exactly what should be in such lib, but it sounds useful
to me
 
C

Chris Hills

why?

imho many people would use a well designed portable c99 lib

They do now. Many compiler have a lib that can do full C99 It is just
that the compilers and the market don't want C99.
that
covers most of the basic things (which are not so basic to be in the
stdlib) a la boost

Covers "most of the basic things" do you want a C99 library of
something that sort of does some of it ?
at least it would be good for educational reasons (how to write nice
c99 code)

Pointless as no one has C99 compilers.
i don't know exactly what should be in such lib, but it sounds useful
to me

It exists.
 
F

Flash Gordon

Charlie Gordon wrote, On 17/09/07 16:00:
Types allocation macros can help make code more readable, without casts, yet
detect some mismatches.:

#include <stdlib.h>
#define alloc_type(type) ((type*)malloc(sizeof(type)))
#define alloc_array(type,n) ((type*)malloc((n) * sizeof(type)))

char *p = alloc_array(char, 100);
int *p = alloc_array(int, 100);
float *p = alloc_array(int, 100); // constraint violation

I don't think your suggestion makes it more readable than the following:
Type *p = malloc(N * sizeof *p);

Also less to change if you want to change Type from float to double.

I can see a point to a constructor for a specific type where you are
keeping open the possibility of doing more than merely calling malloc in
the future, but not for your suggested macros.
 
K

Keith Thompson

Army1987 said:
Usually, #ifndef __STDC__ is (was) used to check whether features
introduced in ANSI C89 not present in K&R C (e.g. ## token-pasting
operator) are available. A compiler which *does* define __STDC__
but to something other than 1 is very likely to have them.

But you can't be sure *which* C89-specific features are supported.
The meaning of defining __STDC__ to anything other than 1 is not
defined by any standard; it's defined only by the documentation of a
particular implementation.

A compiler that supports *all* C89/C90 features will define __STDC__
as 1. (It must; defining __STDC__ as 1 is one of the required
features.)

(On the other hand, there's nothing to stop a perverse non-conforming
compiler from defining __STDC__ as 1; the standard coes not constrain
non-conforming implementations.)
 
K

Keith Thompson

Flash Gordon said:
Charlie Gordon wrote, On 17/09/07 16:00: [...]
Types allocation macros can help make code more readable, without
casts, yet detect some mismatches.:
#include <stdlib.h>
#define alloc_type(type) ((type*)malloc(sizeof(type)))
#define alloc_array(type,n) ((type*)malloc((n) * sizeof(type)))
char *p = alloc_array(char, 100);
int *p = alloc_array(int, 100);
float *p = alloc_array(int, 100); // constraint violation

I don't think your suggestion makes it more readable than the following:
Type *p = malloc(N * sizeof *p);

Also less to change if you want to change Type from float to double.

I can see a point to a constructor for a specific type where you are
keeping open the possibility of doing more than merely calling malloc
in the future, but not for your suggested macros.

I agree completely *if* we're just talking about C (as we normally do
here). But the original article in this thread asserted a requirement
to compile the same code as C and as C++. Assuming such a
requirement, using a macro to hide the ugly cast from C programmers
and the ugly use of malloc() from C++ programmers makes some sense.
 
M

Mark McIntyre

*You* rely on that all the time.

I'm unclear why you' chose to emphasise the 'you' in the above
sentence. That aside, while its true you rely on QoI at all times,
there's a minor difference between relying on QoI to diagnose optional
not-technically-faults and having an implementation that doesn't
diagnose gibberish and/or constraint violations.

The fact that your compiler doesn't
print "Congratulations! Out of cheese!" when you write a*_=6^%7q++*;
is thanks merely to quality of implementation.

I can assure you, I've never had an out of cheese error - for one
thing, I can spell wizzard.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
M

Mark McIntyre

If you rely on getting a useful diagnostic for an implicit conversion
from int to a pointer, you are also relying on Quality of
Implementation. The standard only says that "a diagnostic" is required,

Thats the point tho - a diagnostic is *required*. Whereas it isn't
required (in C89) for no-prototype-in-scope.
but doesn't require any useful information to be included in the
diagnostic. "Warning: This program may contain errors" is perfectly
acceptable as far as the standard is concerned.

So is "warning: this program may contain nuts". So what ?
As a tiny counter example, I submit that gcc 4.1.2 without any -W*

Note that gcc doesn't claim to conform to any C standard (without the
addition of a forest of flags).

--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
?

=?iso-2022-kr?q?=1B=24=29CHarald_van_D=0E=29=26=0F

(On the other hand, there's nothing to stop a perverse non-conforming
compiler from defining __STDC__ as 1; the standard coes not constrain
non-conforming implementations.)

Worse yet, there's nothing preventing nonconforming implementations from
changing the value of __STDC__ in the middle of preprocessing. GCC does
this on some platforms (but not all!).
 
C

CBFalconer

Charlie said:
.... snip ...

Types allocation macros can help make code more readable, without
casts, yet detect some mismatches.:

#include <stdlib.h>
#define alloc_type(type) ((type*)malloc(sizeof(type)))
#define alloc_array(type,n) ((type*)malloc((n) * sizeof(type)))

char *p = alloc_array(char, 100);
int *p = alloc_array(int, 100);
float *p = alloc_array(int, 100); // constraint violation

But you need none of that gubris. The following is correct and
adequate (no defines):

#include <stdlib.h>
char *p = malloc(100 * sizeof *p);
int *q = malloc(100 * sizeof *q);
float *r = malloc(100 * sizeof *r); /* no violation */

You may notice a slight consistency in the code. You can pick up
the malloc statement unchanged and insert it whereever you wish.
 
C

CBFalconer

Mark said:
(e-mail address removed) (Richard Tobin) wrote:
.... snip ...


I can assure you, I've never had an out of cheese error - for one
thing, I can spell wizzard.

Oh? :) wizard.
 
J

Jerry Coffin

[ ... ]
But are these "pre-standard" compilers? Or just non-standard compilers?

I believe most of them I've looked at are pre-standard. In fact, my
primary use of a number of them was only slightly post-standard itself.
Most I've kept track of at all seem to have had little or no updating in
years.
 
R

Richard Heathfield

CBFalconer said:
Oh? :) wizard.

Clearly you are not a fan of Terry Pratchett's "Discworld" novels, in which
one of the principal characters has "wizzard" emblazoned on his pointy
hat. (Not only can the character not spell, but he can't spell either.)
 
C

Chris Thomasson

[...]
#include <stdlib.h>
#define alloc_type(type) ((type*)malloc(sizeof(type)))
#define alloc_array(type,n) ((type*)malloc((n) * sizeof(type)))

char *p = alloc_array(char, 100);
int *p = alloc_array(int, 100);
float *p = alloc_array(int, 100); // constraint violation

Why not calloc?
 
C

CBFalconer

Richard said:
CBFalconer said:

Clearly you are not a fan of Terry Pratchett's "Discworld" novels,
in which one of the principal characters has "wizzard" emblazoned
on his pointy hat. (Not only can the character not spell, but he
can't spell either.)

You are, as usual, accurate. I am glad I included a smiley. It
has avoided a completely ingratiating apology.
 
C

CBFalconer

Chris said:
[...]
#include <stdlib.h>
#define alloc_type(type) ((type*)malloc(sizeof(type)))
#define alloc_array(type,n) ((type*)malloc((n) * sizeof(type)))

char *p = alloc_array(char, 100);
int *p = alloc_array(int, 100);
float *p = alloc_array(int, 100); // constraint violation

Why not calloc?

Use of calloc is (almost always) a pure waste.
 
K

Keith Thompson

Chris Thomasson said:
[...]
#include <stdlib.h>
#define alloc_type(type) ((type*)malloc(sizeof(type)))
#define alloc_array(type,n) ((type*)malloc((n) * sizeof(type)))

char *p = alloc_array(char, 100);
int *p = alloc_array(int, 100);
float *p = alloc_array(int, 100); // constraint violation

Why not calloc?

Why calloc?

calloc initializes the newly allocated object to all-bits-zero, which
isn't necessarily meaningful for floating-point or pointer types, and
which is likely to be a waste of time if the program is going to
initialize it anyway.
 
C

Chris Thomasson

Keith Thompson said:
Chris Thomasson said:
[...]
#include <stdlib.h>
#define alloc_type(type) ((type*)malloc(sizeof(type)))
#define alloc_array(type,n) ((type*)malloc((n) * sizeof(type)))

char *p = alloc_array(char, 100);
int *p = alloc_array(int, 100);
float *p = alloc_array(int, 100); // constraint violation

Why not calloc?

Why calloc?

calloc initializes the newly allocated object to all-bits-zero, which
isn't necessarily meaningful for floating-point or pointer types, and
which is likely to be a waste of time if the program is going to
initialize it anyway.

True.
 
C

Charlie Gordon

Keith Thompson said:
Flash Gordon said:
Charlie Gordon wrote, On 17/09/07 16:00: [...]
Types allocation macros can help make code more readable, without
casts, yet detect some mismatches.:
#include <stdlib.h>
#define alloc_type(type) ((type*)malloc(sizeof(type)))
#define alloc_array(type,n) ((type*)malloc((n) * sizeof(type)))
char *p = alloc_array(char, 100);
int *p = alloc_array(int, 100);
float *p = alloc_array(int, 100); // constraint violation

I don't think your suggestion makes it more readable than the following:
Type *p = malloc(N * sizeof *p);

Also less to change if you want to change Type from float to double.

I can see a point to a constructor for a specific type where you are
keeping open the possibility of doing more than merely calling malloc
in the future, but not for your suggested macros.

I agree completely *if* we're just talking about C (as we normally do
here). But the original article in this thread asserted a requirement
to compile the same code as C and as C++. Assuming such a
requirement, using a macro to hide the ugly cast from C programmers
and the ugly use of malloc() from C++ programmers makes some sense.

These macros, along with corresponding free_type and free_array could be
implemented differently for the C++ target, using new and delete.
Hiding the gory details does help ;-)
 
C

Charlie Gordon

CBFalconer said:
But you need none of that gubris. The following is correct and
adequate (no defines):

#include <stdlib.h>
char *p = malloc(100 * sizeof *p);
int *q = malloc(100 * sizeof *q);
float *r = malloc(100 * sizeof *r); /* no violation */

You may notice a slight consistency in the code. You can pick up
the malloc statement unchanged and insert it whereever you wish.

Of course, but keep in mind the OP's question: he wants his code to compile
and function the same as both C and C++ code.
Your proposal does fit that goal.
While your code is very elegant, it cannot be used for void *p.
 

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
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top