Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Why I Hate C

772 views
Skip to first unread message

Xah Lee

unread,
Jul 13, 2012, 9:38:10 PM7/13/12
to
〈Programing: Why I Hate C〉
http://xahlee.info/comp/why_i_hate_C_lang.html

for your amusement.

-------------------------

I despise C the language, not because of particular technical aspect, or lacking some functionality such as lacking {automatical memory management, module system, namespace, list/hashtable datatype, complex number datatype, regex, function closure, function as value, OOP support, functional programing support, …}, none of that, but on certain sloppiness that's in the bones of C. (pretty much like unix (they bootstrap each other (it's scam booting scam)))

Perhaps the best simple example to illustrate, is its invention of the format function printf (first of all, F��� THE NAME.). Completely ad hoc, inflexible, cryptic syntax and semantics. When i first learned it (thru Perl. (C/Unix has a knack like virus. Now it's in about every lang.)), i went WTF is this? (i came from Mathematica). The printf can print hex, but with fixed representation of the digits, and can't do arbitrary n-based number system. It can print decimal in several formats, but in a bunch of ad hoc fixed ways. And did i mention cryptic syntax? The syntax and semantics isn't extensible in any general way.

There it is, the C language! In C, just about anything it does, it's done in a {ad hoc, fixed, inflexible, non-extensible, cryptic} way, and with a PRETENSE that it is done for speed and efficiency. Note the word “PRETENSE” here. That's important. I don't dislike C because it's a low-level, system language, designed for speed, but because there's a strong HACK element in its blood.

(to this day, due to C's spread of printf, many programers don't really understand what's n-based number system, they just recognize {binary, oct, hex} when they see a string of 0123456789abcdef. And if you show them hex number system using decimal digits in a list, they would be wildly flabbergasted and goes “WHY would you ever want do that??”. To this day, the hex with 0…9a…f have so ingrained in every computing spec. In particular, RGB color e.g. #c2c2c2. (the RGB color spec, is a entire story of complete ad hoc f��� by itself (e.g. ad hoc range of 0 to 255, just because it is convenient at the time!). (not sure who started it, probably unix X11 first popularized it.)))

• Extensive ad hoc syntax. So, we need to increment a counter often. Instead of working on a better compiler, let's invent a short syntax on the spot! Thus was born these abomination: {i++, ++i, i--, --i, =+, …}. And witness the syntax soup: {i++, ++i, for(;;){}, while(){}, 0x123, expr1 ? expr2 : expr3, sprint(…%s…,…), …}. These are ad hoc, cryptic, inflexible, non-extensible, syntaxes — the nature of C. (➲ The Concepts and Confusions of Prefix, Infix, Postfix and Fully Nested Notations)

• the use of bitmask as boolean parameters. (to this day, there are programers who don't understand the difference, saying that bitmask is the most efficient way to “encode” boolean parameters. Encode? Encode their ass. (this again, spread like virus. You see it in perl/python regex flags. Did i mention cryptic? (and WTF is a flag?))) (i've wrote this one out in full: Programing Language Design: the Hack of Bitmask Used as Boolean Parameters.)

• the include as a lib system. No namespace. Granted, in the 1970s, computing resources are meager. Many of C's issues we can't really blame C. But, the key point i want to emphasize is, that everything in C is done is a sloppy no-design way without any apology. If pressed, the C types delight in the ad hoc cryptic nature as hackery. (much inherited by Perl) So, C's include has gone into Perl, and from Perl to PHP. (luckly, include fell off starting with Perl in the late 1990s. Most langs now have a namespace/module system.)

• cryptic error code. This have been transfused into the veins of unix. You have to check the exit code, then you need to decode the error code. And here we onto the related bitmask f��� as in unix.

C and unix are such a sloppy scumbag that they act like a virus. (this point has been well exposited by lisper Richard P Gabriel's 〈The Rise of “Worse is Better”〉.) C spawned csh, C++, Perl, Java, Pretty Home Page (aka PHP) (and the entire C-like syntax langs), C#, Go Lang. They ride on sloppiness and speed which masquerade as portability and distributed like drugs. The whole C Unix things spread like drugs, in particular: unix, perl, Apache, MySQL. Their slogan is often “MOST Popular in Industry!”. And as a consequence, usually “Industry STANDARD”! O, and there is one thing that always accompanies these: $FREE$! (as in, free drugs!)

So, C++ is better? if you think C++ fixed C, then this whole essay has been written in vain. C++ is far worse. (in the context of this essay, Java can be considered as a improvement of C.)

• The Rise of “Worse is Better” (1991) By Richard P Gabriel. @ http://dreamsongs.com/RiseOfWorseIsBetter.html
• Defective C++ (2007) By Yossi Kreinin. @ http://yosefk.com/c++fqa/defective.html

• The Nature of the Unix Philosophy
• Lambda in Python 3000
• Pattern Matching vs Lexical Grammar Specification
• Unix Pipe as Functional Language
• Computer Language Design: What's List Comprehension and Why is It Harmful?
• Language, Purity, Cult, and Deception
• Scheme & Failure

yours truely,

Xah

A.L.

unread,
Jul 13, 2012, 9:43:31 PM7/13/12
to
On Fri, 13 Jul 2012 18:38:10 -0700 (PDT), Xah Lee <xah...@gmail.com>
wrote:

>?Programing: Why I Hate C?
[...]
>So, C++ is better? if you think C++ fixed C, then this whole essay has been written in vain. C++ is far worse. (in the context of this essay, Java can be considered as a improvement of C.)
>

Of course, Lisp is better. The only problem: Lisp is dead.

A.L.

polos...@gmail.com

unread,
Jul 14, 2012, 9:14:32 AM7/14/12
to
Xah Lee Writing:
> C you

Of course C is bad, leaving it alone.
Of course C++ is worse, leaving it on its own.
Of course you can add Lisp to the mix -- and quickly everything is easy to fix.

Pascal J. Bourguignon

unread,
Jul 14, 2012, 9:42:50 AM7/14/12
to
C++ is not so bad:
http://www.informatimago.com/articles/life-saver.html#intelib

And even in C you can write:

#include <stdio.h>
#include <stdlib.h>
#include <ecl/ecl.h>


const char* forms[]={" \
(defun fact (n) \
(if (<= n 1) \
1 \
(* n (fact (- n 1))))) \
"," \
(defun fact-loop () \
(loop for i from 0 below 30 do \
(format t \" ~3D ! ~A ~33D~%\" \
i \
\"==\" \
(fact i)))) \
"," \
(fact-loop) \
",0};



int main(int argc,char** argv){
int i;
cl_boot(argc,argv);
atexit(cl_shutdown);
for(i=0;forms[i];i++){
si_safe_eval(3,c_string_to_object(forms[i]),Cnil,OBJNULL);}
return(0);}

--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.

RG

unread,
Jul 14, 2012, 11:17:21 AM7/14/12
to
In article <87394u7...@kuiper.lan.informatimago.com>,
"Pascal J. Bourguignon" <p...@informatimago.com> wrote:

> polos...@gmail.com writes:
>
> > Xah Lee Writing:
> >> C you
> >
> > Of course C is bad, leaving it alone.
> > Of course C++ is worse, leaving it on its own.
> > Of course you can add Lisp to the mix -- and quickly everything is easy to
> > fix.
>
> C++ is not so bad:
> http://www.informatimago.com/articles/life-saver.html#intelib

https://github.com/rongarret/Ciel

rg

visplo...@gmail.com

unread,
Sep 11, 2012, 8:03:22 AM9/11/12
to
So what programs have you done in lisp?
What websites can I go to that you have done in lisp?
Are you much happier with the results?
Do you run them websites on archlinux?

ccc31807

unread,
Sep 11, 2012, 9:07:37 AM9/11/12
to
On Saturday, July 14, 2012 11:17:21 AM UTC-4, RG wrote:
> https://github.com/rongarret/Ciel

I find this interesting, but it raises a question in my mind. Two questions, in fact. Perl, Python, Ruby, and a number of other languages are written in C. Why not just write the initial code in C? ECL and other Lisps are compiled to C. Why not just write it in C to begin with? (These aren't the questions, just points made with rhetorical questions.)

First, is there any Common Lisp implementation that compiles directly into machine code? I don't know the answer, I'm asking to find out.

Second, why are other languages (e.g., Perl) written in C? I think I already know the answer to this one, but not really sure.

Thanks, CC.

Frode V. Fjeld

unread,
Sep 11, 2012, 9:16:13 AM9/11/12
to
ccc31807 <cart...@gmail.com> writes:

> First, is there any Common Lisp implementation that compiles directly
> into machine code? I don't know the answer, I'm asking to find out.

Of those implementations that are in widespread use, most compile
directly to machine code.

> Second, why are other languages (e.g., Perl) written in C? I think I
> already know the answer to this one, but not really sure.

It's probably because Unix is effectively a "C" OS. Windows is similar
although leaning somewhat more towards C++ (while Microsoft is trying to
shift it to a Microsoft-only runtime). This fact permeates both the
technology and "software culture" on these systems (including the
popular "high-level" programming languages).

--
Frode V. Fjeld

Pascal J. Bourguignon

unread,
Sep 11, 2012, 10:09:48 AM9/11/12
to
Not really. Unix is a syscall OS. Syscalls are as hard to code in C as
they are in Lisp. Actually, C needs an assembly library to call
syscalls.

Now of course, that'd concern only the kernel. Libraries are also parts
of the "OS", and since they're written in C, you want a C FFI to use
them.

But once you have the syscall API and the C FFI done, you don't have
anything to do directly with C to write any language implementation.

Frode V. Fjeld

unread,
Sep 11, 2012, 4:42:03 PM9/11/12
to
"Pascal J. Bourguignon" <p...@informatimago.com> writes:

> "Frode V. Fjeld" <fro...@gmail.com> writes:
>
>> It's probably because Unix is effectively a "C" OS. Windows is similar
>> although leaning somewhat more towards C++ (while Microsoft is trying to
>> shift it to a Microsoft-only runtime). This fact permeates both the
>> technology and "software culture" on these systems (including the
>> popular "high-level" programming languages).
>
> Not really. Unix is a syscall OS. Syscalls are as hard to code in C as
> they are in Lisp. Actually, C needs an assembly library to call
> syscalls.

This is almost completely irrelevant to what I wrote.

> But once you have the syscall API and the C FFI done, you don't have
> anything to do directly with C to write any language implementation.

This too.

--
Frode V. Fjeld

Kaz Kylheku

unread,
Sep 11, 2012, 4:55:39 PM9/11/12
to
On 2012-09-11, Frode V. Fjeld <fro...@gmail.com> wrote:
> "Pascal J. Bourguignon" <p...@informatimago.com> writes:
>
>> "Frode V. Fjeld" <fro...@gmail.com> writes:
>>
>>> It's probably because Unix is effectively a "C" OS. Windows is similar
>>> although leaning somewhat more towards C++ (while Microsoft is trying to
>>> shift it to a Microsoft-only runtime). This fact permeates both the
>>> technology and "software culture" on these systems (including the
>>> popular "high-level" programming languages).
>>
>> Not really. Unix is a syscall OS. Syscalls are as hard to code in C as
>> they are in Lisp. Actually, C needs an assembly library to call
>> syscalls.
>
> This is almost completely irrelevant to what I wrote.

Yes. Although Unix is a "syscall OS", whenever a syscall is a pointer to
something, that something is invariably some kind of C data structure
or C data type, and that makes it easier for C.

Although the syscall has to implement some special calling convention (like loading
arguments into registers and invoking a trap instruction, and then pulling
the errno value from some register, etc) it's not so far off semantically from
a C function call.

Though the syscall sequence may be as hard to code in C as it is in Lisp, the
arguments do not require any special treatment in C once you have the wrapper.

For instance, once we have a C callable wrapper for invoking the stat system
call, then we just declare a "struct stat" variable and take its address
to pass a pointer to this function.

Pascal J. Bourguignon

unread,
Sep 11, 2012, 5:56:26 PM9/11/12
to
That doesn't make a reason to write a line of C code in an other
programming language implementation.

One reason to choose to use C, is to avoid generating native code, and
instead use C as a portable assembler. Unfortunately, the C virtual
machine doesn't seem too efficient, and often people prefer to go down
to C implementation or native platform dependant tricks (playing with
pointers or C type representations). The consequence is that in general
you cannot port a programming language implementation as a simple C
recompilation. Hence the lack of CL implementations on eg. iOS.

kalvi...@gmail.com

unread,
Sep 14, 2012, 8:18:47 AM9/14/12
to
As a (embedded) programmer, I am quite tired of seeing this s**t over and over again:

typedef enum
{
BITMASK_1 = 0x01,
BITMASK_2 = 0x02,
BITMASK_3 = 0x04
}
Bitmask;

typedef enum
{
ONE,
TWO,
THREE
}
Number;

typedef unsigned char uint8;

uint8 someFunction(Bitmask bm1, Bitmask bm2)
{
return (bm1 | bm2);
}

int main ()
{
Bitmask bm1 = 0;
Number n1 = 1;
Bitmask bm2 = someFunction(n1, bm1);
Number n2 = someFunction(7, 2) ^ bm2;
return 0;
}

Giorgos Keramidas

unread,
Sep 15, 2012, 12:38:32 PM9/15/12
to
The distinction between syscalls and library functions is kept
relatively 'clear' in well-formed UNIX systems. The manual pages of
'section 2' are explicitly marked as 'system calls'. The manual pages
of 'section 3' are also explicitly marked as 'library functions'.

The line is a bit blurry when libc.so is concerned, because it exports
symbols for *both* types of functions, but I fully agree iwth Pascal
here. Once you have a syscall layer and you have a way to write
user-level libraries on top of it, UNIX is not necessarily tied to C, or
to Lisp for that matter.

What's happening though is that as soon as you move outside of your own
'software bubble', and you _have_ to use someone else's code, the vast
majority of user-mode libraries for UNIX *are* written in C. Just like
if you are programming for the Android platform, it's far easier to find
libraries in Java instead of Objective Caml, or Fortran.

Nick Keighley

unread,
Sep 20, 2012, 11:36:26 AM9/20/12
to
On Sep 14, 1:18 pm, kalvin.n...@gmail.com wrote:

> As a (embedded) programmer, I am quite tired of seeing this s**t over
> and over again:
>
> typedef enum
> {
>     BITMASK_1 = 0x01,
>     BITMASK_2 = 0x02,
>     BITMASK_3 = 0x04}
> Bitmask;

#define BIT(N) (1 << (N))

> typedef enum
> {
>     ONE,
>     TWO,
>     THREE}
> Number;

well yes I admit i'd puke over that one. Everyon knows its

#define zero 48
#define one 49
#define two 50

> typedef unsigned char uint8;

better:-
typedef unsigned char octet;

> uint8 someFunction(Bitmask bm1, Bitmask bm2)
> {
>     return (bm1 | bm2);
> }

what's the problem? I'm not sure what someFunction() does but if you
need to OR stuff together why not? I object to the brackets around the
return expression.

> int main ()
> {
>     Bitmask bm1 = 0;
>     Number n1 = 1;
>     Bitmask bm2 = someFunction(n1, bm1);
>     Number n2 = someFunction(7, 2) ^ bm2;
>     return 0;
> }

well it's imaginary code. its not clear what you are objecting to.

void lampOn (int lampId)
{
octet* port = lampDesc[lampId].port;
octet bit = lampDesc[lampId].bit;
setBit (port, bit);
}

low level code is always going to be nasty. You abstract it away.

void mainLampOn (void)
{
lampOn (MAIN_LAMP);
}

until eventually your application level code is speaking in
application language

void runMainTransmitter ()
{
startAntenaRotation ();
BlackHeatOn ():
azimuth = readAzimuth ();
suppressMainBang();
}

is it really so different in other languages?


Nick Keighley

unread,
Sep 20, 2012, 11:48:55 AM9/20/12
to
On Sep 11, 2:07 pm, ccc31807 <carte...@gmail.com> wrote:
> On Saturday, July 14, 2012 11:17:21 AM UTC-4, RG wrote:
> >https://github.com/rongarret/Ciel

> I find this interesting, but it raises a question in my mind. Two questions, in fact. Perl, Python, Ruby, and a number of other languages are written in C.

maybe. Often a core or kernel is written in C and the bulk (especially
libraries) in an implementaion language. many languages are largely
self-hosted. Lisp certainly is.

> Why not just write the initial code in C?

what?

> ECL and other Lisps are compiled to C.

many Lisps aren't though.

> Why not just write it in C to begin with?

have you written anything in a language other than C? Have you written
any C? Open the Perl cookbook find something non-trivial but not too
long and write a C program that does the same thing. Now try it with
lisp. Are you enlightened?

In a nutshell Perl and Lisp make it easy to do things that are hard in
C. The implementor then does all the hard work for you

> (These aren't the questions, just points made with rhetorical questions.)

why?

> First, is there any Common Lisp implementation that compiles directly into machine code? I don't know the answer, I'm asking to find out.
>
> Second, why are other languages (e.g., Perl) written in C?

C is pretty low level it is close to the machine. C can be written to
be fairly efficient. C is almost universally available. There's a C
compiler for *everything*. This makes boot strapping your
implementaion easier.

> I think I already know the answer to this one, but not really sure.

so we have to guess what you think?

> Thanks, CC.

kalvi...@gmail.com

unread,
Sep 21, 2012, 4:43:46 AM9/21/12
to

torstai, 20. syyskuuta 2012 18.36.26 UTC+3 Nick Keighley kirjoitti:
> On Sep 14, 1:18 pm, kalvin.n...@gmail.com wrote:
>
>
>
> > As a (embedded) programmer, I am quite tired of seeing this s**t over
>
> > and over again:
>
> >
>
> > typedef enum
>
> > {
>
> >     BITMASK_1 = 0x01,
>
> >     BITMASK_2 = 0x02,
>
> >     BITMASK_3 = 0x04}
>
> > Bitmask;
>
> #define BIT(N) (1 << (N))

This typedef is just fine. Its intention is to declare a enumerated constant values for the bitmasks. No problem here.

>
>
>
> > typedef enum
>
> > {
>
> >     ONE,
>
> >     TWO,
>
> >     THREE}
>
> > Number;
>
> well yes I admit i'd puke over that one. Everyon knows its
>

This is just fine as well. The intention is to declare enumerated constants with type identifier Number.

> > typedef unsigned char uint8;
>
> better:-
>
> typedef unsigned char octet;
>

Intention here is to declare a datatype for an unsigned 8-bit byte. Both versions are just fine, no problem here either.

>
> > uint8 someFunction(Bitmask bm1, Bitmask bm2)
>
> > {
>
> >     return (bm1 | bm2);
>
> > }
>
> what's the problem? I'm not sure what someFunction() does but if you
> need to OR stuff together why not? I object to the brackets around the
> return expression.

This function itself is just fine. It takes two bitmasks as parameter and returns thei boolean OR'd value. Plain and simple.

But now comes the s**t: I will comment this case by case:

> > int main ()
>
> > {
> >     Bitmask bm1 = 0;

Okay, we have declared a type Bitmask which is declared as enumerated values, but the C compiler doesn't complain that we assign an integer instead of those enumerated values. In my opinion, the compiler should reject this code.

> >     Number n1 = 1;

Same thing here as above. Number is an enumerated type and the compiler should check that we assign only declared values, and reject this code.

> >     Bitmask bm2 = someFunction(n1, bm1);

Here the same situation: We pass a Number instead of Bitmask. The compiler should reject this one.

> >     Number n2 = someFunction(7, 2) ^ bm2;

Same as above. We pass integers instead of Bitmask enumerated values and we assign a Bitmask to an Integer, which as of different types. The C compiler is happy with this, but in my opinion the C compiler should reject this.

> >     return 0;
>
> > }
> well it's imaginary code. its not clear what you are objecting to.

I am objecting to C language type system. It is way too sloppy and allows mixing different kind of declared data types. I do know that usually the C compilers have some kind of strict type checking options which will do more thorough type checking, but it is still too weak. I would like to see strict Ada-like type checking instead, which would reject this kind of sloppy coding.

I need to maintain some legacy code which is written originally using this sloppy style, and I have encountered numerous hard to find bugs that results from this sloppy type system of C compiler.

> low level code is always going to be nasty. You abstract it away.

Low level coding is nasty, but at least the compiler should ensure correct type compatibility. If we want to play tricks with values and variables, the compiler should insist in using proper explicit type casting.

> is it really so different in other languages?

Not really. For instance Java has similar problems. Strict type checking should be a must. Programmers object using a language which is too strict. Why? Because people are just plain lazy :) But if the compilers make sure that you cannot write sloppy code, it will pay the effort in longer run.

- Kalvin

Kaz Kylheku

unread,
Sep 21, 2012, 3:13:00 PM9/21/12
to
On 2012-09-21, kalvi...@gmail.com <kalvi...@gmail.com> wrote:
> torstai, 20. syyskuuta 2012 18.36.26 UTC+3 Nick Keighley kirjoitti:
>> > typedef enum
>> > {
>> >     BITMASK_1 = 0x01,
>> >     BITMASK_2 = 0x02,
>> >     BITMASK_3 = 0x04}
>> > Bitmask;
>>
>> #define BIT(N) (1 << (N))
>
> This typedef is just fine. Its intention is to declare a enumerated constant
> values for the bitmasks. No problem here.

Yes there is a problem. What are you daft?

The enumerated type has three values in its domain: BITMASK_1, BITMASK_2
and BITMASK_3. A value such as BITMASK_1 | BITMASK_2 is not in the
domain of the enumerated type.

Yet the code uses that type to represent it:

Bitmask x = BITMASK_1 | BITMASK_2;

What that means is that x now has a value which is not one of the declared
constants, and therefore outside of the type.

Note that this was banished from C++ long ago, because C++ was given
type-safe enumerations.

That's one good reason to write your C in such a way that it also compiles with
a C++ compiler.

You cannot use enumerations for bitmasks, period. It's conceptually wrong,
and banished by the better dialect of C known as C++.

>> > typedef enum
>> > {
>> >     ONE,
>> >     TWO,
>> >     THREE}
>> > Number;
>> well yes I admit i'd puke over that one. Everyon knows its
>
> This is just fine as well. The intention is to declare enumerated constants
> with type identifier Number.

No it is not fine, because now you have constants ONE, TWO, and THREE
whose values are 0, 1 and 2, respectively.

I suggest you read a C tutorial.

kalvi...@gmail.com

unread,
Sep 22, 2012, 8:13:27 AM9/22/12
to
perjantai, 21. syyskuuta 2012 22.13.04 UTC+3 Kaz Kylheku kirjoitti:
> On 2012-09-21, kalvi...@gmail.com <kalvi...@gmail.com> wrote:
>
> > torstai, 20. syyskuuta 2012 18.36.26 UTC+3 Nick Keighley kirjoitti:
>
> >> > typedef enum
>
> >> > {
>
> >> >     BITMASK_1 = 0x01,
>
> >> >     BITMASK_2 = 0x02,
>
> >> >     BITMASK_3 = 0x04}
>
> >> > Bitmask;
>
> >>
>
> >> #define BIT(N) (1 << (N))
>
> >
>
> > This typedef is just fine. Its intention is to declare a enumerated constant
>
> > values for the bitmasks. No problem here.
>
>
>
> Yes there is a problem. What are you daft?
>
>
>
> The enumerated type has three values in its domain: BITMASK_1, BITMASK_2
>
> and BITMASK_3. A value such as BITMASK_1 | BITMASK_2 is not in the
>
> domain of the enumerated type.
>
> Yet the code uses that type to represent it:
>
> Bitmask x = BITMASK_1 | BITMASK_2;
>
> What that means is that x now has a value which is not one of the declared
> constants, and therefore outside of the type.

Your comment reveals that you haven't done embedded C coding for a while. The intention of the code snippet was clearly to define a set of bits for boolean operations. So the intent domain of the operations is boolean and my comment is valid. You comment is correct technically.

> Note that this was banished from C++ long ago, because C++ was given
> type-safe enumerations.

Like I commented in my first post, I need to maintain legacy C code. And even with the current GCC using default compiler options my example compiles clean without any errors or warnings. C++ has some nice improvements, I agree.

> That's one good reason to write your C in such a way that it also compiles with a C++ compiler.

I agree on this.

> You cannot use enumerations for bitmasks, period. It's conceptually wrong,
> and banished by the better dialect of C known as C++.

Like I stated above, the intention of the programmer was to declare a bit mask. And this is valid C code.

> >> > typedef enum
> >> > {
> >> >     ONE,
> >> >     TWO,
> >> >     THREE}
> >> > Number;
>
> > This is just fine as well. The intention is to declare enumerated constants
> > with type identifier Number.
>
> No it is not fine, because now you have constants ONE, TWO, and THREE
> whose values are 0, 1 and 2, respectively.

Okay, I must admit that this was a bad example from me. More appropriate would have been something like this to make my point more obvious:

typedef enum {
STATE_UNDEFINED,
STATE_CLOSED,
STATE_CLOSING,
STATE_OPENING,
STATE_OPEN
} State;

> I suggest you read a C tutorial.

And I suggest that you read ANSI C and K&R (2nd ed.) about enums ;-) Basically "In ANSI C, the expressions that define the value of an enumerator constant always have int type; thus, the storage associated with an enumeration variable is the storage required for a single int value. An enumeration constant or a value of enumerated type can be used anywhere the C language permits an integer expression." (http://msdn.microsoft.com/en-us/library/whbyts4t.aspx).

Aleksej Saushev

unread,
Oct 3, 2012, 12:30:34 PM10/3/12
to
Nick Keighley <nick_keigh...@hotmail.com> writes:

> On Sep 14, 1:18О©╫pm, kalvin.n...@gmail.com wrote:
>
>> As a (embedded) programmer, I am quite tired of seeing this s**t over
>> and over again:

...

>> typedef unsigned char uint8;
>
> better:-
> typedef unsigned char octet;

JFYI, "unsigned char" is not necessarily an octet.
(And embedded programmer should know it better, in fact.)

If you really want octet, C has type for it (if you have octets at all),
it is called "uint8_t".


--
HE CE3OH...

Kaz Kylheku

unread,
Oct 3, 2012, 1:07:45 PM10/3/12
to
On 2012-10-03, Aleksej Saushev <as...@inbox.ru> wrote:
> Nick Keighley <nick_keigh...@hotmail.com> writes:
>
>> On Sep 14, 1:18 pm, kalvin.n...@gmail.com wrote:
>>
>>> As a (embedded) programmer, I am quite tired of seeing this s**t over
>>> and over again:
>
> ...
>
>>> typedef unsigned char uint8;
>>
>> better:-
>> typedef unsigned char octet;
>
> JFYI, "unsigned char" is not necessarily an octet.
> (And embedded programmer should know it better, in fact.)
> If you really want octet, C has type for it (if you have octets at all),
> it is called "uint8_t".

C storage is divided into bytes, which is the smallest individually addressable
unit of storage. The character types occupy one byte: sizeof(char) is 1
by definition. Bytes must be at least 8 bits wide.

So, if unsigned char is wider than an octet, then your system does not have
octets. (And it cannot be narrower than an octet.)

No type can be smaller than a byte. (Bifields that can occur in structures
or unions can be smaller, but they are not types in their own right. Their
address cannot be taken, nor their size.)

So if char is wider than an octet, it is impossible for uint8_t to provide an
octet. Practically speaking, uint8_t can be nothing other than a typedef for
unsigned char. If unsigned char is not 8 bits wide, then uint8_t will not
exist, and there is a macro to test for that. But you can do the same thing in
C90, like this:

#include <limits.h>

#if CHAR_BIT > 8 /* CHAR_BIT must be at least 8 */
#error "Oops, this program needs bytes to be 8 bits wide
#endif

typedef unsigned char byte_t;

uint8_t is an ugly, redudant C99 stupidity, among many.

The Lisp guys had the decency to standardize a language and then go their
separate ways until a time comes when another standard is really, really
needed to solve actual needs.

Pascal J. Bourguignon

unread,
Oct 3, 2012, 1:33:25 PM10/3/12
to
Kaz Kylheku <k...@kylheku.com> writes:

> So if char is wider than an octet, it is impossible for uint8_t to provide an
> octet.
> Practically speaking, uint8_t can be nothing other than a typedef for
> unsigned char. If unsigned char is not 8 bits wide, then uint8_t will not
> exist, and there is a macro to test for that.

Indeed. It's better to use uint_least8_t et al. from <stdint.h>.
0 new messages