Types in C

K

Keith Thompson

jacob navia said:
Le 23/05/11 23:25, Ian Collins a écrit :

True, but the PURPOSE of typedefs is to HIDE the underlying type so that
source code refers to it INDIRECTLY.

The purpose of that indirection is twofold:
(1) To highlight a CONCEPT of the program:
typedef double CustomerBalance;

(2) To make code portable by abstracting the underlying type
away. (size_t for instance)

The purpose of a typedef is whatever the programmer wants to use it for.
It can be used simply to provide a shorter name for an existing type.
For example:

typedef unsigned long ulong;
typedef struct foo {
/* member declarations */
} foo;

Neither ulong nor foo provides an abstraction; they're both just
aliases.

Typedefs can certainly be *used* for the purposes you describe,
and a tutorial can and should discuss that. But if you want your
readers to understand the concept, I suggest that that should
include an understanding of what typedef means on the language level.

You are conflating the manner in which typedef is *used* with the
way the language defines it.

Incidentally, I've said that a typedef is an alias, and you've agreed
that that's what it does (see above), yet you insist that I'm wrong.
I think we're actually in agreement. Perhaps you'd be able to
acknowledge that if this were coming from someone other than me.
 
K

Keith Thompson

jacob navia said:
Gcc had a multiple precision package for that purpose. It was simple and
efficient and never gave any problems, all features that made it obsolete.

Why make it simple when you can make it very complicated?

They now use GMP, a HUGE package that can multiply numbers of ANY
size, up to thousands of digits precision, complete with assembler
code tailored for each processor, with obscure macros, with thousands
of complications that aren't at all needed for a compiler.

That is progress my friend. PROGRESS means:

If it is simple, it is wrong.

If GMP had been developed specifically to be used by gcc, and
not used in other contexts, I'd probably agree with you; using an
infinite-precision library where, say, 128 bits would be enough
would be overkill (assuming the 128-bit library is simpler than the
infinite-=precision library).

But GMP already exists, and all the effort needed to develop
it has already been expended. The complexity of GMP is huge.
The complexity of adding GMP to gcc is minimal. And it has the
benefit that the previous multiple precision package is no longer
required, no longer needs to be maintained, and is no longer a
potential additional source of bugs.
 
K

Keith Thompson

Shao Miller said:
* I hope to some day purchase some actual standards. The efforts that
have gone into them can certainly save me some time == money while
attempting to write portable C. :)

For almost all purposes, a copy of n1256.pdf is more useful than a
copy of the actual standard. n1256.pdf consists of the C99 standard
with the three Technical Corrigenda merged into it, and marked with
change bars. It's a more accurate depiction of the current state
of the language standard than the C99 standard itself.

For *complete* accuracy, you'd want the C99 standard (costs about
$30, I think) plus the three Technical Corrigenda (available at no
change), but it's difficult to tell where in the C99 standard the
changes have been made; n1256 does that work for you.
 
K

Keith Thompson

Seebs said:
You're doing it wrong.

Don't know the size. Know the *minimum* size. You don't actually need
to know whether something is 32 bits, you just need to know that it's at
least big enough to hold some particular value. For all you know you're
getting a 64-bit type because that's what's fast on this hardware.

If you specify a specific type when a less specific type would do, you hurt
performance on a fair variety of hardware.

Which is why int_least32_t and int_fast32_t exist.
 
M

Malcolm McLean

The complexity of GMP is huge.
The complexity of adding GMP to gcc is minimal.
In comparison to the complexity of developing such a package from
scratch, yes.

But installation of C libraries is a huge problem. Just little things
like the bool problem can turn into major headaches. Then you've got
to supply the library to anyone to whom ypu give source code, which
can quickly turn into having two or more copies of the library on the
machine.
 
K

Keith Thompson

Uncle Steve said:
It's a cognitive semantic quirk. Return kind-of looks like it is a
special function that transfers control to the original caller, and so
I put return values in parenthesis because that's what you do with
real functions. I know it's not a function, but try to tell that to
my brain.

Perhaps omitting the parentheses would help out with your brain
problem. :cool:}

Seriously, I don't use parentheses on return statements precisely
because a return statement is not a function call and I don't
want it to look like one. I do the same with sizeof: "sizeof obj"
rather than "sizeof(obj)".

[...]
I was mostly taking issue with the idea that a derived type is
qualitatively equivalent to a /de-novo/ basic type, which was the
implication given in the way some were using the term 'type' in their
statements -- by my reckoning of their meaning. When the word 'type'
is used with precision similar to a word like 'run' ("the computer
runs"), it is difficult to be entirely sure what is really meant.

I believe you've misunderstood their meaning.

You seem to be seeing some ambiguity in the word "type". I don't
believe there is any such ambiguity; the word is well defined by the C
standard, and I think that most people here other than you have been
using it consistently and correctly.

There are basic types and derived types. Both basic types and derived
types are types. There are no user-defined basic types. There are
user-defined derived types. The statements "There are no user-defined
basic types" and "There are no user-defined types" are very different;
in particular, the first statement is true, and the second is false.

The following paragraph is the same as the previous with the
substitution of a few phrases.

There are men and women. Both men and women are people. There are no
pregnant men. There are pregnant women. The statements "There are no
pregnant men" and "There are no pregnant people" are very different; in
particular, the first statement is true, and the second is false.
Actual printed copies are fairly expensive from what I gather.
Available from Global Engineering Documents, as per the C-FAQ, section
5.2.

I paid $18 for my PDF copy of the C99 standard from ansi.org; I think
it's $30 now. (You can also pay several hundred dollars for the same thing.)
Once you have the PDF, you can print it if you like, but I've
never bothered. But as I said elsethread, N1256 is better, for
most purposes, than the original C9 standard, and it's free.
 
S

Seebs

It's a cognitive semantic quirk. Return kind-of looks like it is a
special function that transfers control to the original caller, and so
I put return values in parenthesis because that's what you do with
real functions. I know it's not a function, but try to tell that to
my brain.

That is, in fact, exactly why I *don't* use () on it; because it's the
opposite of a function call.
I was mostly taking issue with the idea that a derived type is
qualitatively equivalent to a /de-novo/ basic type, which was the
implication given in the way some were using the term 'type' in their
statements -- by my reckoning of their meaning. When the word 'type'
is used with precision similar to a word like 'run' ("the computer
runs"), it is difficult to be entirely sure what is really meant.

Heh.

Yeah, I think:
I was mostly taking issue with the idea that a derived type is
qualitatively equivalent to a /de-novo/ *basic* type, which was the
(emphasis mine)

is where the gap came in. I wouldn't claim you could define a basic
type, because the set of basic types is listed exhaustively. :)
Actual printed copies are fairly expensive from what I gather.
Available from Global Engineering Documents, as per the C-FAQ, section
5.2.

The modern one can be gotten for $20ish, as I recall, as a PDF.

-s
 
S

Seebs

Language lawyering... Hmm. Dictionary.com does not seem to contain a
definition that supports your imputation of the pejorative.

Huh?

It's got nothing to do with the definitions; it's to do with Gricean maxims.

Language is used to communicate. If people say something, they thought it
was adding information.

If instead of saying:
Uncle Steve is a millionaire
I say
Uncle Steve claims he is a millionaire
I have added words; the added words are logically presumed to add
information.
Ha, well on Usenet nothing can be taken for granted. What say you do
and who you say you are is always subject to verification.

I think the difference is...

If I make a technical claim, and you think I'm wrong, it's perfectly
possible that I'm wrong but not lying.

If I make a claim about my qualifications or experience, and you think
I'm wrong, it's not in general possible that I'm wrong but not lying.

So one of them is an accusation of lying, while one of them is an accusation
of error-or-lying. It admits a charitable interpretation. And I don't
know any competent computer people who are offended by the allegation that
they could be mistaken. We make mistakes. There is a reason that there
is a category of software tools called "debuggers".

-s
 
B

BartC

Seebs said:
I've used several. There have been MANY systems where larger types were
faster than smaller types. It's common.

Idle question: Have you ever used an Intel processor? Like, an x86?

I wrote a little routine which does a trivial tight loop on objects.

chars: 4.084635 secs.
shorts: 4.161859 secs.
ints: 2.729034 secs.
longs: 3.284039 secs.
quads: 3.134092 secs.

So, if you "knew" that you needed a 16-bit type, and used short, you'd
be taking a 50% performance hit for picking an inefficient type. If all
you need is "can store values up to 30000", that would be silly. Heck,

I've just written a routine where using short is 10% faster than int,
because it allocates a large number of them and therefore uses half the
memory (and half the bandwidth).

Not much difference, but in other cases using a wider type than is necessary
can cause more severe problems ...
you'd get better performance on *64-bit* objects than you would on
16-bit shorts.

.... such as running out of memory completely.
 
U

Uncle Steve

That is, in fact, exactly why I *don't* use () on it; because it's the
opposite of a function call.

As far as bad coding habits go, it's fairly benign.
Heh.

Yeah, I think:

(emphasis mine)

is where the gap came in. I wouldn't claim you could define a basic
type, because the set of basic types is listed exhaustively. :)

That's just asking for trouble...
The modern one can be gotten for $20ish, as I recall, as a PDF.

I wouldn't mind a printed copy, if only for the reason that reading
books on a smallish LCD screen is still difficult.



Regards,

Uncle Steve
 
U

Uncle Steve

Huh?

It's got nothing to do with the definitions; it's to do with Gricean maxims.

Language is used to communicate. If people say something, they thought it
was adding information.

If instead of saying:
Uncle Steve is a millionaire
I say
Uncle Steve claims he is a millionaire
I have added words; the added words are logically presumed to add
information.

So long as you aren't being redundant, and there's no shortage of
redundant English from poor writers. But I like the suggestion
anyways. Don't forget about the mansion and yacht.
I think the difference is...

If I make a technical claim, and you think I'm wrong, it's perfectly
possible that I'm wrong but not lying.

If I make a claim about my qualifications or experience, and you think
I'm wrong, it's not in general possible that I'm wrong but not lying.

So one of them is an accusation of lying, while one of them is an accusation
of error-or-lying. It admits a charitable interpretation. And I don't
know any competent computer people who are offended by the allegation that
they could be mistaken. We make mistakes. There is a reason that there
is a category of software tools called "debuggers".

Opinions are divided on the subject of debuggers. I believe Linus is
said to have opposed an in-kernel debugger for the reason that its
availability would lead to lazy programming practices. I don't know
whether the anecdote is true, but it is an interesting thought.



Regards,

Uncle Steve
 
K

Keith Thompson

Uncle Steve said:
As far as bad coding habits go, it's fairly benign.

As benign coding habits go, it's fairly bad. :cool:}

[...]
That's just asking for trouble...

I don't know what you mean by that.
I wouldn't mind a printed copy, if only for the reason that reading
books on a smallish LCD screen is still difficult.

It would probably be cheaper to get a PDF (either the standard for about
$30 or N1256 for free) and print it yourself, than to buy a printed copy
from ISO or ANSI. And then you'd have both the PDF and the paper copy.

Personally, I find the PDF much more useful than a paper copy would be;
I prefer "cut and paste" to be figurative rather than literal.
 
U

Uncle Steve

Perhaps omitting the parentheses would help out with your brain
problem. :cool:}

Possibly, but I've decided on self-hypnosis as the cure. I'll get
back to you just as soon as I ... zzzzzzzzz.
Seriously, I don't use parentheses on return statements precisely
because a return statement is not a function call and I don't
want it to look like one. I do the same with sizeof: "sizeof obj"
rather than "sizeof(obj)".

You're correct, of course. And in the end, with the admission of
parenthetic infidelity, I reveal the fact that I was never taught
C or computer science by a qualified professional.
[...]
I was mostly taking issue with the idea that a derived type is
qualitatively equivalent to a /de-novo/ basic type, which was the
implication given in the way some were using the term 'type' in their
statements -- by my reckoning of their meaning. When the word 'type'
is used with precision similar to a word like 'run' ("the computer
runs"), it is difficult to be entirely sure what is really meant.

I believe you've misunderstood their meaning.

I must have, because the reaction to my comments were fairly strongly
worded.
You seem to be seeing some ambiguity in the word "type". I don't
believe there is any such ambiguity; the word is well defined by the C
standard, and I think that most people here other than you have been
using it consistently and correctly.

The "standard definition" doesn't seem to be the obvious one to
colloquial English speakers, but then we normally expect less rigor in
casual conversation.
There are basic types and derived types. Both basic types and derived
types are types. There are no user-defined basic types. There are
user-defined derived types. The statements "There are no user-defined
basic types" and "There are no user-defined types" are very different;
in particular, the first statement is true, and the second is false.

With you so far.
The following paragraph is the same as the previous with the
substitution of a few phrases.

There are men and women. Both men and women are people. There are no
pregnant men. There are pregnant women. The statements "There are no
pregnant men" and "There are no pregnant people" are very different; in
particular, the first statement is true, and the second is false.


I paid $18 for my PDF copy of the C99 standard from ansi.org; I think
it's $30 now. (You can also pay several hundred dollars for the same thing.)
Once you have the PDF, you can print it if you like, but I've
never bothered. But as I said elsethread, N1256 is better, for
most purposes, than the original C9 standard, and it's free.

The addendum in its original form is probably only of interest to
language historians. I don't know if I'd like to pay for a PDF
version, but a smartly bound printed copy would be a nice thing to
have.



Regards,

Uncle Steve
 
U

Uncle Steve

As benign coding habits go, it's fairly bad. :cool:}

Should I cry "uncle" at this point? Maybe not, it might confuse
people. I'll just add it to the list of pending corrections I have to
make to my code. I'll review it all eventually, at least.
[...]
That's just asking for trouble...

I don't know what you mean by that.

There's apparently something going on between Mr. Seebach and Mr.
Miller having to do with prior claims. I don't know the details, but
it at least it seems they have a history of taking jabs at each
other, which is what the above appeared to be.
It would probably be cheaper to get a PDF (either the standard for about
$30 or N1256 for free) and print it yourself, than to buy a printed copy
from ISO or ANSI. And then you'd have both the PDF and the paper copy.

Personally, I find the PDF much more useful than a paper copy would be;
I prefer "cut and paste" to be figurative rather than literal.

I have a thing for bound volumes, except that I can rarely afford to
buy the damn things.



Regards,

Uncle Steve
 
S

Seebs

So long as you aren't being redundant, and there's no shortage of
redundant English from poor writers. But I like the suggestion
anyways. Don't forget about the mansion and yacht.
:)

Opinions are divided on the subject of debuggers.

Sure. But the fact that they're there to have opinions about testifies
that bugs are a reality.

-s
 
J

Joe Pfeiffer

Uncle Steve said:
As far as bad coding habits go, it's fairly benign.

It was within the last decade or so that I learned the parens weren't
required! Hmmm, I wonder.... looking at Kernighan's original C
tutorial (which was what I learned the language from, before K&R was
published), I see he used them. Anybody know whether they were actually
required back then?
 
S

Shao Miller

Should I cry "uncle" at this point? Maybe not, it might confuse
people. I'll just add it to the list of pending corrections I have to
make to my code. I'll review it all eventually, at least.

Well, it could be considered "ugly" just as the redundant parentheses in
'sizeof (obj)' or 'x = (y * 2) + 1' might be ugly, and I don't ever use
it, but it could be handy for debug-builds... After including standard
headers, you could:

#if DEBUG
# define return(x_) return (returning(__LINE__), (x_))
#endif

Or some other such fun.
[...]
Yeah, I think:

I was mostly taking issue with the idea that a derived type is
qualitatively equivalent to a /de-novo/ *basic* type, which was the
(emphasis mine)

is where the gap came in. I wouldn't claim you could define a basic
type, because the set of basic types is listed exhaustively. :)

That's just asking for trouble...

I don't know what you mean by that.

There's apparently something going on between Mr. Seebach and Mr.
Miller having to do with prior claims. I don't know the details, but
it at least it seems they have a history of taking jabs at each
other, which is what the above appeared to be.

I sincerely doubt his use of "claim" there has anything to do with the
friendly advice I attempted to offer you earlier. And no, no jabs intended.

But I believe he's mistaken (not lying!) about "listed exhaustively,"
anyway. "Basic types" include[6.2.5p14] "...char, the signed and
unsigned integer types, and the floating types..." "Signed integer
types" include[6.2.5p4] "...standard and extended signed integer
types..." "Extended signed integer types", if any, are
implementation-defined[6.2.5p4], so they're not exhaustively listed in
the Standard, but I'd expect them to be documented with the
implementation. Same with "extended unsigned integer types".

In fact, perhaps it'd still be conforming for an implementation to
include a documented extension which _does_ allow user-defined basic
types. How would you like that? :)

Enjoy.
 
D

Dr Nick

Seebs said:
That is, in fact, exactly why I *don't* use () on it; because it's the
opposite of a function call.

The "it's not a function call" argument has never really stacked up for
me. I know it's not a function call, but neither are 'if' or 'for' and
try writing those without them. On the other hand, 'exit' is about as
close to return as you can get (from main anyway) and yet does need
them.

The argument that works for me is "you don't need them, they don't add
anything to readability, so why put them in?". I did use them in my
early days; I think I picked it up from K&R 1 and picked up not using
them from here.
 
U

Uncle Steve

Well, it could be considered "ugly" just as the redundant parentheses in
'sizeof (obj)' or 'x = (y * 2) + 1' might be ugly, and I don't ever use
it, but it could be handy for debug-builds... After including standard
headers, you could:

#if DEBUG
# define return(x_) return (returning(__LINE__), (x_))
#endif

Or some other such fun.

That would be handy to track down a silent deadlock, such as an
endless loop in a function, or a wait on a system call that somehow
never returns.
[...]
Yeah, I think:

I was mostly taking issue with the idea that a derived type is
qualitatively equivalent to a /de-novo/ *basic* type, which was the
(emphasis mine)

is where the gap came in. I wouldn't claim you could define a basic
type, because the set of basic types is listed exhaustively. :)

That's just asking for trouble...

I don't know what you mean by that.

There's apparently something going on between Mr. Seebach and Mr.
Miller having to do with prior claims. I don't know the details, but
it at least it seems they have a history of taking jabs at each
other, which is what the above appeared to be.

I sincerely doubt his use of "claim" there has anything to do with the
friendly advice I attempted to offer you earlier. And no, no jabs intended.

But I believe he's mistaken (not lying!) about "listed exhaustively,"
anyway. "Basic types" include[6.2.5p14] "...char, the signed and
unsigned integer types, and the floating types..." "Signed integer
types" include[6.2.5p4] "...standard and extended signed integer
types..." "Extended signed integer types", if any, are
implementation-defined[6.2.5p4], so they're not exhaustively listed in
the Standard, but I'd expect them to be documented with the
implementation. Same with "extended unsigned integer types".

In fact, perhaps it'd still be conforming for an implementation to
o> include a documented extension which _does_ allow user-defined basic
types. How would you like that? :)

That might be interesting, but I don't know how you'd do it. IIAC,
gcc (obviously) uses a huge number of builtin functions to handle
operations on it's large range of basic types. The compiler would
have to define a way to expose those interfaces to user code, which
sounds like it might require serious layer violations. I hope I've
got the terminology correct there.

But the ability to define arbitrary types would be neat. I previously
asked whether Perl or Python allowed this sort of thing; perhaps I
should expand the question to ask whether there are any languages at
all that make this possible? I can't imagine that it hasn't been
done before, but C is not an obvious fit for that kind of thing.
Dynamic modification of the language itself (which is what we are
talking about here) to add basic capabilities is not something C was
designed to do.

Possibly Ruby -- I'll look in to it if I find the time.



Regards,

Uncle Steve
 
K

Keith Thompson

Dr Nick said:
The "it's not a function call" argument has never really stacked up for
me. I know it's not a function call, but neither are 'if' or 'for' and
try writing those without them. On the other hand, 'exit' is about as
close to return as you can get (from main anyway) and yet does need
them.

Yes, parentheses are heavily overloaded in C.

The "it's not a function call" argument is why I distinguish between
function calls and if/while/for by whitespace:

if (cond) ...
while (cond) ...
func(arg);

In my own style, a function call has the '(' immediately following the
function name; adding a space between 'if' and '(' makes it look less
like a function call. And I've been trying to develop the habit of
writing "sizeof (int)" rather than "sizeof(int)".

Oh, and exit(0) *is* a function call, regardless of how it happens to
behave.
The argument that works for me is "you don't need them, they don't add
anything to readability, so why put them in?". I did use them in my
early days; I think I picked it up from K&R 1 and picked up not using
them from here.

That works too.
 

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,780
Messages
2,569,611
Members
45,283
Latest member
JoannaGrif

Latest Threads

Top