is "typedef int int;" illegal????

K

kuyper

David R Tribble wrote:
....
Type names like 'long long' have the advantage of being decoupled
from the exact word size of the underlying CPU. That's why you
can write reasonably portable code for machines that don't have
nice multiple-of-8 word sizes.

int_least64_t shares that same characteristic in a more scalable
fashion.
Some programmers may prefer using 'int_least64_t' over 'long long'.
But I don't.

I would prefer using int64 over either of those alternatives, with
int64 being given the same meaning currently attached to int_least64_t.
 
K

kuyper

Douglas said:
Why is that objectionable?

Because it's the wrong solution, and adopting it into the standard
creates justification for anticipating (hopefully incorrectly) that
this wrong solution is the way that future versions of the standard
will handle new type sizes.
... It avoided using up another
identifier for a new keyword, did not embed some assumed
size in its name (unlike several extensions),

You consider that an advantage. I think it's a disadvantage to have a
type whose miniminum required size corresponds to 64 bits, but giving
it a name which does not make that fact explicit.

Also, I've heard it criticised because of the fact that it's form makes
it something unique in the standard: a doubled keyword that is neither
a syntax error nor eqivalent to the corresponding un-doubled keyword. I
don't know much about the internals of compiler design, but I've seen
comments on someone who thought he did, who claimed that this
distinction unnecessarily imposed an (admittedly small) additional
level of complexity on the parser.
and
matched the choice of some of the existing extensions.

I recognise the practical necesity of taking into consideration
existing practice. My criticism of 'long long' was aimed primarily at
those who created it in the first place as an extension to existing
implementations.
 
J

jacob navia

Douglas A. Gwyn a écrit :
We hope you defined the appropriate stuff in <stdint.h>
and <inttypes.h>, since that is what portable programs
will have to use instead of implementation-specific names.

Note also that you have made lcc-win32 non standards
conformant. You should have used an identifier reserved
for use by the C implementation, not one that is
guaranteed to be available for the application.

The use of int128 is only there IF you

#include <int128.h>

Otherwise you can use the identifier int128 as you want.

jacob
 
R

Richard Bos

Douglas A. Gwyn said:
We hope you defined the appropriate stuff in <stdint.h>
and <inttypes.h>, since that is what portable programs
will have to use instead of implementation-specific names.

Note also that you have made lcc-win32 non standards conformant.
^
even more
HTH; HAND.

Richard
 
R

Richard Bos

(e-mail address removed) wrote:

[ about "long long": ]
Also, I've heard it criticised because of the fact that it's form makes
it something unique in the standard: a doubled keyword that is neither
a syntax error nor eqivalent to the corresponding un-doubled keyword. I
don't know much about the internals of compiler design, but I've seen
comments on someone who thought he did, who claimed that this
distinction unnecessarily imposed an (admittedly small) additional
level of complexity on the parser.

More so than "long int", "signed int", and "unsigned short int" already
did? If so, I can't help thinking that the difference must have been
truly slight.

Richard
 
J

jacob navia

Jordan said:
In that case, why not use stdint.h and int128_t, int_least128_t, and
int_fast128_t?

Because that would force ALL users of stdint.h to accept int128_t and
all the associated machinery, what is probably not what all of them want.

But the name int128 is not "cast in stone" and since I suppose the names
intXXX_t are reserved I could use those.

Basically this type is implemented using lcc-win32 specific extensions
like operator overloading, what allows to easily define new types. This
extensions are disabled when you invoke the compiler under the "no
extensions" mode. If I would put the 128 bit integers in the stdint
header, the operator overloading required would not work under the "ansi
c" environment, and problems would appear. That is why I use a special
header that will be used only by people the want those integer types.

Of course there is a strict ANSI C interface for 128 bit integers, but
if you use it, you would have to write

int128 a,b,c;
...
c = i128add(a,b);

instead of

c = a+b;
 
J

Jordan Abel

Douglas A. Gwyn a écrit :

The use of int128 is only there IF you

#include <int128.h>

Otherwise you can use the identifier int128 as you want.

jacob

In that case, why not use stdint.h and int128_t, int_least128_t, and
int_fast128_t?
 
J

Jordan Abel

(e-mail address removed) wrote:

[ about "long long": ]
Also, I've heard it criticised because of the fact that it's form makes
it something unique in the standard: a doubled keyword that is neither
a syntax error nor eqivalent to the corresponding un-doubled keyword. I
don't know much about the internals of compiler design, but I've seen
comments on someone who thought he did, who claimed that this
distinction unnecessarily imposed an (admittedly small) additional
level of complexity on the parser.

More so than "long int", "signed int", and "unsigned short int" already
did? If so, I can't help thinking that the difference must have been
truly slight.

Those still have only one of each keyword present. It's not like "long
long" acts as a 'pseudo-keyword' - "long int signed long" is a valid
name for the type.
 
M

Michael Mair

jacob said:
Douglas A. Gwyn a écrit :

The use of int128 is only there IF you

#include <int128.h>

Otherwise you can use the identifier int128 as you want.

This is IMO no good solution; if someone defined
typedef struct {
....
} int128;
in a library and one of your users wants to use this
library and another one which uses the
implementation-provided 128 bit exact width signed
integer type, he or she runs into a rather unnecessary
problem.
IMO, providing appropriate definitions in the
appropriate headers is better.

FWIW: I have seen enough "int64" and "Int64" structure
typedefs to assume that there may be the same for
128 bits.

Cheers
Michael
 
W

Wojtek Lerch

David R Tribble said:

I have to say that I find it rather vague and simplistic, and can't find
where it answers my questions. I have absolutely no clue how you wanted to
handle implementations that are neither clearly little-endian nor clearly
big-endian. You didn't propose to ban them, did you?

/* Bit/byte/word order */

#define _ORD_BIG 0 /* Big-endian */
#define _ORD_LITTLE 1 /* Little-endian */

#define _ORD_BITF_HL 0 /* Bitfield fill order */
#define _ORD_BYTE_HL 0 /* Byte order within shorts */
#define _ORD_WORD_HL 0 /* Word order within longs */

What about implementations with one-byte shorts? What if the bit order
within a short doesn't match the bit order in a char? What if the byte
order within a two-byte short doesn't match the byte order within a half of
a four-byte long? What about the halves of an int? What about
implementations with three-byte longs? What if the most significant bits
sit in the middle byte? Or if the three most significant bits are mapped to
the least significant bit of the three bytes?
This was written in 1995, before 'long long' existed, so I'd have
to add a few more macros, including:

#define _ORD_LONG_HL n

My suggestion is just one of hundreds of ways to describe
endianness, bits sizes, alignment, padding, etc., that have been
invented over time. None of which ever made it into ISO C.

Perhaps because they all made the incorrect assumption that in every
conforming implementation, every integer type must necessarily be either
little endian or big endian?

Personally, I think it would be both easier and more useful not to try to
classify all types on all implementations, but instead to define names for
big- and little-endian types and make them all optional. For instance:

uint_be32_t -- a 32-bit unsigned type with no padding bits and a
big-endian representation, if such a type exists.

The representation is big-endian if:

* for any two value bits located in different bytes, the bit whose byte
has a lower address represents a higher value
* for any two value bits located in the same byte, the order of their
represented values matches the order of the values they represent in
unsigned char
 
J

Jordan Abel

Because that would force ALL users of stdint.h to accept int128_t and
all the associated machinery, what is probably not what all of them want.

Why? What machinery is associated with int128_t that c99 doesn't
_already_ say is permitted in stdint.h?

You'd have
int128_t, int_least128_t, int_fast128_t, etc typedefs,
INT128_MIN, INT128_MAX, UINT128_MAX, and the associated LEAST and FAST
ones as well, INT128_C(x) and UINT128_C(x) in stdint.h

{PRI,SCN}[diouxX]{FAST,LEAST,}128 in inttypes.h

what else do you need?
But the name int128 is not "cast in stone" and since I suppose the names
intXXX_t are reserved I could use those.

Basically this type is implemented using lcc-win32 specific extensions
like operator overloading, what allows to easily define new types. This
extensions are disabled when you invoke the compiler under the "no
extensions" mode. If I would put the 128 bit integers in the stdint
header, the operator overloading required would not work under the "ansi
c" environment, and problems would appear.

Why not implement it as a standard type so that it can _always_ be used,
with nothing but an #ifdef INT128_MAX to check if it's present?
That is why I use a special header that will be used only by people
the want those integer types.

Of course there is a strict ANSI C interface for 128 bit integers, but
if you use it, you would have to write

int128 a,b,c;
...
c = i128add(a,b);

instead of

c = a+b;

why? why not implement it as a standard type, with the compiler knowing
about it?

#ifdef INT_LEAST128_MAX
int_least128_t a,b,c;
c = a+b;
#else
#error No 128-bit integer type available
#endif
 
D

Douglas A. Gwyn

jacob said:
Because that would force ALL users of stdint.h to accept int128_t and
all the associated machinery, what is probably not what all of them want.

If the programs don't try to use the type then the extra definitions
are of no consequence.
... If I would put the 128 bit integers in the stdint
header, the operator overloading required would not work under the "ansi
c" environment, and problems would appear. That is why I use a special
header that will be used only by people the want those integer types.

You ought to rethink your design. If your compiler knows the
type as __int128 (for example) then <stdint.h> need only refer
to that name. You may have to define a testable macro for
your extended environment in order for the standard header to
know whether that type is supported or not, but that kind of
thing is quite common in implementations already.
 
D

Douglas A. Gwyn

You consider that an advantage. I think it's a disadvantage to have a
type whose miniminum required size corresponds to 64 bits, but giving
it a name which does not make that fact explicit.

Then you should use <stdint.h>, which was introduced at the
same time. None of the "keyword" types has ever had a
specific size embedded in its name.
Also, I've heard it criticised because of the fact that it's form makes
it something unique in the standard: a doubled keyword that is neither
a syntax error nor eqivalent to the corresponding un-doubled keyword. I
don't know much about the internals of compiler design, but I've seen
comments on someone who thought he did, who claimed that this
distinction unnecessarily imposed an (admittedly small) additional
level of complexity on the parser.

If a parser generator is used (e.g. yacc) there is no significant
problem. If a hand-coded parser is used, it's nearly trivial to
handle. (Look ahead one token, for example. In Ritchie's PDP-11
C compiler a "long" counter was incremented, and there was no
diagnostic for multiple "longs". It is trivial to test for a
count of 1, 2, or many and do the right thing for each case.)
 
K

kuyper

Douglas said:
Then you should use <stdint.h>, which was introduced at the
same time.

I plan to, should our client ever give us permission to use anything
more advanced than C94. However, I wasn't complaining about the absence
of those types - I know they exists. I was objecting to the presence of
"long long", and in particular to it's presence in some pre-C99
implementations. It's that presence which forced the C committee to
accept "long long" in the same revision as the preferred alternatives.
... None of the "keyword" types has ever had a
specific size embedded in its name.

And, in retrospect, I don't approve of that fact.
 
D

David R Tribble

Wojtek said:
I have to say that I find it rather vague and simplistic, and can't find
where it answers my questions. I have absolutely no clue how you wanted to
handle implementations that are neither clearly little-endian nor clearly
big-endian. You didn't propose to ban them, did you?

No, that's why there are three endianness macros. This allows for,
say, the PDP-11 mixed-endian 'long int' type:

#define _ORD_BIG 0 /* Big-endian */
#define _ORD_LITTLE 0 /* Little-endian */

#define _ORD_BITF_HL 0 /* Bitfield fill order */
#define _ORD_BYTE_HL 0 /* Byte order within shorts */
#define _ORD_WORD_HL 1 /* Word order within longs */

What about implementations with one-byte shorts?

Obviously the macro names could be better.

What if the bit order within a short doesn't match the bit order in a char?
What if the byte order within a two-byte short doesn't match the byte order
within a half of a four-byte long? What about the halves of an int? What about
implementations with three-byte longs? What if the most significant bits
sit in the middle byte? Or if the three most significant bits are mapped to
the least significant bit of the three bytes?

Then we need more macros with better names.
You're not saying that this is an unsolvable problem, are you?

Perhaps because they all made the incorrect assumption that in every
conforming implementation, every integer type must necessarily be either
little endian or big endian?

I didn't make that assumption.

Personally, I think it would be both easier and more useful not to try to
classify all types on all implementations, but instead to define names for
big- and little-endian types and make them all optional. For instance:
uint_be32_t -- a 32-bit unsigned type with no padding bits and a
big-endian representation, if such a type exists.

How do you tell if those types are not implemented?

More to the point, how do you tell portably what byte order plain
'int' is implemented with?

-drt
 
D

David R Tribble

And, in retrospect, I don't approve of that fact.

Then you probably don't approve of Java, Perl, awk, ksh, FORTRAN,
BASIC, etc., or most other programming languages, either.

-drt
 
W

Wojtek Lerch

David R Tribble said:
Then we need more macros with better names.
You're not saying that this is an unsolvable problem, are you?

Pretty much, depending on what exactly you call the problem and what kind of
a solution you find acceptable.

Let's concentrate on implementations that have 16-bit short types with no
padding bits. There are 20922789888000 possible permutations of 16 bits,
and the C standard doesn't disallow any of them. Even though it's
theoretically possible to come up with a system of macros allowing programs
to distinguish all the permutations, I don't think it would be very useful
or practical. For all practical purposes, a distinction between big endian,
little endian, and "other" is sufficient. There are no existing "other"
implementations anyway.

In practice, a simple one-bit solution like your is perfectly fine.
Unfortunately, it only covers practical implementations; therefore, it
wouldn't be acceptable as a part of the standard.
I didn't make that assumption.

Correct me if I'm wrong, but you did seem to make the assumption that there
are only two possible byte orders within a short, and that there are only
two possible "word orders" within a long, and that knowing those two bits of
information (along with the common stuff from <limits.h>) gives you complete
or at least useful knowledge about the bit order of all integer types (in
C89).

If I indeed misunderstood something, could you explain how you would use
your macros in a program to distinguish between implementations where an
unsigned short occupies two 9-bit bytes, has two padding bits, and
represents the value 0x1234 as

(a) 0x12, 0x34 ("big endian", with a padding bit at the top of each byte)
(b) 0x24, 0x68 ("big endian", with a padding bit at the bottom of each
byte)
(b) 0x22, 0x64 ("big endian", with a padding bit in the middle of each
byte)
(c) 0x34, 0x12 ("little endian", padding at the top)
(d) 0x68, 0x24 ("little endian", padding at the bottom)
(e) 0x23, 0x14 ("middle endian", with the middle bits in the first byte, a
padding bit at the top of each byte)
How do you tell if those types are not implemented?

More to the point, how do you tell portably what byte order plain
'int' is implemented with?

You don't. It doesn't make sense to talk about the "byte order" without
assuming that the value bits are grouped into bytes according to their
value; and that assumption is not portable. At least not in theory.

Using your method, how do you tell where the padding bits are located? If
you can't, how useful is it to know the "byte order"?
 
E

Eric Sosman

David R Tribble wrote On 03/30/06 16:55,:
[...]

Wojtek said:
I have to say that I find it rather vague and simplistic, and can't find
where it answers my questions. I have absolutely no clue how you wanted to
handle implementations that are neither clearly little-endian nor clearly
big-endian. You didn't propose to ban them, did you?


No, that's why there are three endianness macros. This allows for,
say, the PDP-11 mixed-endian 'long int' type:

#define _ORD_BIG 0 /* Big-endian */
#define _ORD_LITTLE 0 /* Little-endian */

Does the Standard require that the 1's bit and the
2's bit of an `int' reside in the same byte? Or is the
implementation free to scatter the bits of the "pure
binary" representation among the different bytes as it
pleases? (It must, of course, scatter the corresponding
bits of signed and unsigned versions in the same way.)

If the latter, I think there's the possibility (a
perverse possibility) of a very large number of permitted
"endiannesses," something like

(sizeof(type) * CHAR_BIT) !
-----------------------------
(CHAR_BIT !) ** sizeof(type)

Argument: There are `sizeof(type) * CHAR_BIT' bits (value,
sign, and padding) in the object, so the number of ways to
permute the bits is the factorial of that quantity. But C
cannot detect the arrangement of individual bits within a
byte, so each byte of the object divides the number of
detectably different arrangements by `CHAR_BIT!'.

For an `int' made up of four eight-bit bytes, this
gives 32! / (8! ** 4) ~= 1e17 "endiannesses," or one tenth
of a billion billion.
 
J

Jordan Abel

(a) 0x12, 0x34 ("big endian", with a padding bit at the top of each
byte)
(b) 0x24, 0x68 ("big endian", with a padding bit at the bottom of each
byte)
(b) 0x22, 0x64 ("big endian", with a padding bit in the middle of each
byte)
(c) 0x34, 0x12 ("little endian", padding at the top)
(d) 0x68, 0x24 ("little endian", padding at the bottom)
(e) 0x23, 0x14 ("middle endian", with the middle bits in the first byte, a
padding bit at the top of each byte)

You forgot 0x09, 0x34, big-endian with the padding bits at the top of
the word, which is, to me, the most obvious of all.
 
W

Wojtek Lerch

Jordan Abel said:
You forgot 0x09, 0x34, big-endian with the padding bits at the top of
the word, which is, to me, the most obvious of all.

The truth is I didn't think of it because my example originally had 8-bit
bytes and no padding. But as far as my point is concerned, it doesn't
matter which combination is the most obvious one, only that there are
zillions of valid combinations.
 

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,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top