a doubt about c

Y

Ya Shou

Hello, friends.

I read some open source c program code, found a problem that let me doubt.
All those programs are using macros to define constants, and did not use an enum to achieve, but I think in the enumeration constants is very convenient.
Enumeration defines constants used in c++, but not seen any in c, why?

Thank you.

---- ---- ---- ----
Ya Shou (@54c3)
54c3.blogspot.com
 
J

James Kuyper

Hello, friends.

I read some open source c program code, found a problem that let me doubt.
All those programs are using macros to define constants, and did not use an enum to achieve, but I think in the enumeration constants is very convenient.
Enumeration defines constants used in c++, but not seen any in c, why?

This is mostly a cultural thing; it has little to do with any
differences between the way the two languages work. There are definite
advantages to using enumeration constants over macros, but most of those
advantages apply equally well in both languages. However, those
advantages are also relatively minor, which is why it's still
commonplace to use macros instead.

Enumeration constants have the type of the enumeration in C++, whereas
they always have a type of 'int' in C. Because that affects overload
resolution and template instantiation, that can be an important
difference in C++, whereas if C adopted such a rule, it wouldn't make
much difference.
 
A

Angel

Hello, friends.

I read some open source c program code, found a problem that let me doubt.
All those programs are using macros to define constants, and did not use
an enum to achieve, but I think in the enumeration constants is very
convenient.

There are some advantages of using enums over #defines in C (such as
allowing compilers to do some additional checks) but unlike C++, the
advantages in C are fairly minor.
Enumeration defines constants used in c++, but not seen any in c, why?

It's mainly historical. Enums were originally not a part of the C
language when K&R designed it; they were first added in C89. Many
sources still use #defines over enums, and both forms are acceptable
as in C there is functionally very little difference between them.
 
S

Shao Miller

...
I read some open source c program code, found a problem that let me doubt.
All those programs are using macros to define constants, and did not use an enum to achieve, but I think in the enumeration constants is very convenient.
Enumeration defines constants used in c++, but not seen any in c, why?
...

If you mean "integer constant expressions," I prefer to use 'enum's in C
wherever possible.

If an integer constant expression needs to be used as part of an '#if'
pre-processing directive, then I will '#define' and use a macro whose
definition will not contain any identifiers (except other macros) or
keywords.

#define ALL_ONES_CHAR ((1 << CHAR_BIT) - 1)

enum cv {
cv_minute = 60,
cv_timeout = 2 * cv_minute,
cv_sector_size = 1 << 9,
cv_max_buf_size = 4 * cv_sector_size,
/* ... */
cv_zero = 0
};
 
K

Keith Thompson

Angel said:
It's mainly historical. Enums were originally not a part of the C
language when K&R designed it; they were first added in C89. Many
sources still use #defines over enums, and both forms are acceptable
as in C there is functionally very little difference between them.

Enums are older than that. If I recall correctly, they were added
shortly after K&R1, which was published in 1978.

One drawback of enums is that they're only of type int; you can't use
them to define constants of other types, including floating-point types.

Arguably using an enum to define a single constant:

enum { max = 1000 };

is an abuse of the feature, which is intended to be used to define a
group of closely related constants. Of course that stop me from using
it that way.

What I'd really like to see is for C to adopt C++'s feature, where
a const object of numeric type whose initializer is a constant
expression can be used as a constant:

const int max = 1000;
const double pi = 3.14159265358979;

But it's probably too late to add that to C201X.

(Incidentally, the word "doubt" is not synonymous with "question",
at least not in most dialects of English. A "doubt" generally
implies that you disbelieve something.)
 
L

Lew Pitcher

I think that ints are required to be at least 16 bits wide, so
sizeof (int) is always at least 2
(in all ANSI conforming implementation)

No

sizeof(int) may be 1 in an ISO (and ANSI) conforming implementation
Granted, CHAR_BIT would have to be greater than 8 in such a configuration.
 
K

Keith Thompson

dr.oktopus said:
I think that ints are required to be at least 16 bits wide,

so
sizeof (int) is always at least 2 (in all ANSI conforming
implementation)

No. sizeof (int) is at least 2 on systems with CHAR_BIT == 8,
but if CHAR_BIT >= 16, sizeof (int) can be 1.

Almost all modern implementations, and probably all actual hosted
implemenations, have CHAR_BIT==8, but I understand that there are
implemntations for DSPs (digital signal processors) with larger
CHAR_BIT values.

Note that a "byte" is defined in C by the value of CHAR_BIT; if
CHAR_BIT is 16, then a byte is 16 bits, not the more common 8 bits.

Incidentally, it makes more sense to talk about ISO conforming
implementations. ISO issued the C99 standard; ANSI, the US standards
body, adopted it after puplication, as did other national standards
bodies. (The previous standard was originally published by ANSI
in 1989 and adopted by ISO in 1990, and ANSI members have a strong
presence on the ISO committee, but ANSI itself has no real standing
outside the US.) Referring to ISO C can also avoid confusion since,
for historical reasons, the phrase "ANSI C" commonly refers to the
1989/1990 standard, not the current 1999 standard.
 
J

Joe Pfeiffer

dr.oktopus said:
I think that ints are required to be at least 16 bits wide, so
sizeof (int) is always at least 2 (in all ANSI conforming
implementation)

A brief search of the C99 standard failed to turn this up. I was able
to find (in 6.2.5):

A ``plain'' int object has the natural size suggested by the
architecture of the execution environment (large enough to contain
any value in the range INT_MIN to INT_MAX as defined in the header
<limits.h>).

(which doesn't say you can't have a 1-byte int). That said, I don't
think I've ever encountered a compiler (even for an 8 bit processor)
that didn't use at least a 16 bit int.
 
I

Ian Collins

Yeah, #defines and macros have their place, but this seems like a much
more natural way to define a numerical constant to me.

The place for #define constants is the dustbin of history!
 
S

Shao Miller

The place for #define constants is the dustbin of history!

So then what happens to '#if'? Does it get stuck with numbers that
don't have an associated, meaningful name?
 
E

Eric Sosman

The place for #define constants is the dustbin of history!

I guess you feel the same way about #if?

(Not poking fun at you, really. Various deep thinkers are
of the opinion that the entire preprocessor belongs in the
dustbin, not just the macros; perhaps you're at least partially
allied with them.)
 
N

Nobody

A brief search of the C99 standard failed to turn this up. I was able
to find (in 6.2.5):

A ``plain'' int object has the natural size suggested by the
architecture of the execution environment (large enough to contain
any value in the range INT_MIN to INT_MAX as defined in the header
<limits.h>).

(which doesn't say you can't have a 1-byte int). That said, I don't
think I've ever encountered a compiler (even for an 8 bit processor)
that didn't use at least a 16 bit int.

From 5.2.4.2.1, the smallest permitted values for for INT_MIN and INT_MAX
are:

-- minimum value for an object of type int
INT_MIN -32767 // -(215-1)

-- maximum value for an object of type int
INT_MAX +32767 // 215-1

So you can only have a 1-byte int if you have 16-bit bytes.
 
K

Keith Thompson

Angel said:
I was going by Wikipedia, which claims it was first introduced by ANSI.
But it is quite possible that you are right. I was only five back then
so I don't remember 1978 too well. ;-)

I was %*&*^ at the time. (Hope this article isn't garbled by line
noise.)

According to http://plan9.bell-labs.com/who/dmr/chist.html (yes, the dmr
is Dennis Ritchie):

During 1973-1980, the language grew a bit: the type structure
gained unsigned, long, union, and enumeration types, and
structures became nearly first-class objects (lacking only a
notation for literals).

unsigned, long, and union all appear in K&R1 (1978), but enums and
struct parameters did not.

[...]
 
K

Keith Thompson

DSF said:
May I ask why you feel that way? #define constants certainly have a
potential performance benefit over a const variable. The use of a
#define constant is often replaced with an immediate value, whereas a
const variable is likely to be stored in a static memory pool which is
often part of the program itself. This leaves the potential for
slower execution and a larger program size.

If a const object's initialization is a constant expression, any
decent optimizing compiler will replace any reference to the object
with its value (unless fetching it from memory is actually faster
on the system in question).
 
I

Ian Collins

May I ask why you feel that way?

They are an anachronism. I don't believe in mixing the preprocessor
realm (conditional compilation) with the C code realm. Unfortunately C
has never adopted the C++ definition of const as compile time constant,
so we will be stuck with them for a while longer. I really don't
understand why this change has never been made.
#define constants certainly have a
potential performance benefit over a const variable. The use of a
#define constant is often replaced with an immediate value, whereas a
const variable is likely to be stored in a static memory pool which is
often part of the program itself. This leaves the potential for
slower execution and a larger program size.

Not with a half decent modern compiler.
 
S

Stephen Sprunk

If a const object's initialization is a constant expression, any
decent optimizing compiler will replace any reference to the object
with its value (unless fetching it from memory is actually faster
on the system in question).

AFAICT, that would not be legal since some other code outside the
current compilation unit could cast away the variable's const-ness and
alter its value. It's also not possible to eliminate the object
entirely if some code takes its address with the & operator.

If const objects were actually constant expressions in C rather than
merely read-only objects, as one might naïvely expect (and they are in
C++), that'd be a different matter.

S
 
I

Ian Collins

AFAICT, that would not be legal since some other code outside the
current compilation unit could cast away the variable's const-ness and
alter its value. It's also not possible to eliminate the object
entirely if some code takes its address with the& operator.

The only way to alter the value is to take the address with the &
operator. How does one take the address of a macro constant?
If const objects were actually constant expressions in C rather than
merely read-only objects, as one might naïvely expect (and they are in
C++), that'd be a different matter.

Both the compilers I use will place a variable declared const at a read
only address. So any attempt to change its value will release nasal demons.
 
J

Joe Pfeiffer

Nobody said:
From 5.2.4.2.1, the smallest permitted values for for INT_MIN and INT_MAX
are:

-- minimum value for an object of type int
INT_MIN -32767 // -(215-1)

-- maximum value for an object of type int
INT_MAX +32767 // 215-1

So you can only have a 1-byte int if you have 16-bit bytes.

Thanks. Of course, the macro still doesn't work in that case!
 
E

Eric Sosman

If a const object's initialization is a constant expression, any
decent optimizing compiler will replace any reference to the object
with its value (unless fetching it from memory is actually faster
on the system in question).

AFAICT, that would not be legal since some other code outside the
current compilation unit could cast away the variable's const-ness and
alter its value. [...]

... thus invoking undefined behavior (6.7.3p5). The optimization
is permitted, the non-optimization is permitted, *anything* is
permitted, including scribbling "I Love Lucy" all over the disk.
 
N

Nick Keighley

     I guess you feel the same way about #if?

     (Not poking fun at you, really.  Various deep thinkers are
of the opinion that the entire preprocessor belongs in the
dustbin, not just the macros; perhaps you're at least partially
allied with them.)

C++ still uses the preprocessor. What is the alternative to #include?
Or #if?
 

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,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top