473,396 Members | 2,004 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Is C99 the final C?

I was just thinking about this, specifically wondering if there's any
features that the C specification currently lacks, and which may be
included in some future standardization.

Of course, I speak only of features in the spirit of C; something like
object-orientation, though a nice feature, does not belong in C.
Something like being able to #define a #define would be very handy,
though, e.g:

#define DECLARE_FOO(bar) #define FOO_bar_SOMETHING \
#define FOO_bar_SOMETHING_ELSE

I'm not sure whether the features of cpp are even included in the C
standard though (and GCC has definitely taken quite a nonstandard approach
with regards to certain token expansions and whatnot), but that's one area
of improvement I see.

I would also like to see something along the lines of C++ templating,
except without the really kludgy implementation that the C++ folks decided
to go to ( and without the OOP ).

.... Mike pauses for the sound of a thousand *plonks*

Templates save a lot of time when it comes to commonly-used data
structures, and as they are entirely implemented at compile-time and don't
include, by their definition, OOP (although they can be well suited to
it), I think they would be a nice addition and in the spirit of C.

Your thoughts? I'm sure there's some vitriol coming my way but I'm
prepared 8)

--
Mike's Patented Blocklist; compile with gcc:

i=0;o(a){printf("%u",i>>8*a&255);if(a){printf(".") ;o(--a);}}
main(){do{o(3);puts("");}while(++i);}

Nov 13 '05
193 9343
In article <3F***************@saicmodis.com>, James Kuyper
<ku****@saicmodis.com> writes
No - I think that &&& and ||| would be so rarely used that their
meanings would become trivia questions.

see Rule 36 of the MISTRAY-C C coding standard at
Http://mistray-c.phaedsys.org

It is the antidote to MISRA-C and should raise a smile or three.

I am looking for some code examples to illustrate some of the rules.

regards
Chris

/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills Staffs England /\/\/\/\/\
/\/\/ ch***@phaedsys.org www.phaedsys.org \/\/
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
Nov 13 '05 #51
Sidney Cadot <si****@jigsaw.nl> wrote in message news:<bq**********@news.tudelft.nl>...
Arthur J. O'Dwyer wrote:
The last statement I do not understand. Care to elaborate?

const int foo = 5;
char arr[foo];

Legal C++ (because in C++, const objects are really "constant"),
but illegal C (because 'foo' is an object whose value needn't
be stored [or even computed] at compile time).


This is legal at least in C99, and I think also in C89 (at least my gcc
doesn't even warn on it).


That's because C99 now allows variable-length arrays, so an integer
constant expression is no longer required in that context. However,
they were required in C89 in this context, so if a compiler fails to
issue a diagnostic, it isn't a conforming implementation of C89. All
of the following uses of foo except the one that is marked are still
illegal in C99, because they still require integer constant
expressions:

struct bf_holder{
int bit_field:foo;
} x[foo+1] = // Only legal use of foo in this section.
{[foo] = {10}}; // Subscript for designated initializer

enum {enumeration_value=foo};

switch(x[0].bit_field)
{
case foo:
}

struct bf_holder *p=x+foo;
Nov 13 '05 #52
"Arthur J. O'Dwyer" <aj*@nospam.andrew.cmu.edu> wrote in message news:<Pi**********************************@unix44. andrew.cmu.edu>...
....
is easier for me to grasp. And I think (but this is just IMH
and uneducated O) that C++ compilers need a lot of extra baggage
to deal with constant "consts," and I wouldn't want to foist all
that on C compilers.


I'm curious - why do you think that? I don't know that you're wrong,
but I can't think of any reason why it would be a significant cost.
Nov 13 '05 #53
On Mon, 01 Dec 2003 13:24:23 GMT, in comp.lang.c , pete
<pf*****@mindspring.com> wrote:
Mark McIntyre wrote:

On Sun, 30 Nov 2003 13:54:02 GMT, in comp.lang.c , pete
<pf*****@mindspring.com> wrote:
>'long' might be a better choice
>for when you need an exactly 32-bit integer type.


There's nothing that requires long to be exactly 32 bits any more
than int. Both would be equally nonportable assumptions.


A type which is guaranteed to have at least 32 bits, is a better choice
than one which isn't guaranteed to have at least 32 bits,
for when you need an exactly 32-bit integer type.


*shrug*. I understand your point, but when in implementation-dependent
territory, its quite immaterial what ISO requires, its never going to
safely port anyway so abandon all hope, ye who enter here....
--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.angelfire.com/ms3/bchambless0/welcome_to_clc.html>
----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
Nov 13 '05 #54
In <3F***********@mindspring.com> pete <pf*****@mindspring.com> writes:
Dan Pop wrote:

In <3F**********@mindspring.com> pete <pf*****@mindspring.com> writes:
>Arthur J. O'Dwyer wrote:
>
>> I think // comments are obscene; I have no use for variable-width
>> arrays; any time I need an exactly 32-bit integer type, I'm probably
>> not writing completely portably anyway and might as well use 'int'
>> itself; and so on.
>
>'long' might be a better choice
>for when you need an exactly 32-bit integer type.
Nope. long should be a better choice for when you need a 64-bit
integer type.
The only unwasteful type assignation for the usual processors
currently used in hosted implementations is:

8-bit: char
16-bit: short
32-bit: int
64-bit: long

and there are C89 implementations that do the integral types this way.
No need for a long long at all.

Having int as an "alias" for either short or long was a historical
mistake that should have been exposed and corrected long ago. The C
standards keep blessing it, instead...


That might be the case, if you're talking about implementing C,
but I beleive that Arthur J. O'Dwyer,
was talking about the the C programmer's choice
for when it comes to choosing a type, while writing C code.


The C programmer's choice is not that clear. See below.
I use long to implement psuedorandom number generators
which generate 32 bit values, portably.
I can't do that with int.


It depends on your definition of portability. For current hosted
implementations, int will give you 32 bits, while long may give you more
than that. If you think that being portable to MSDOS is a great idea,
than you have to use long and accept the fact that you're wasting memory
on other platforms. No big deal for scalars, but it may become a
performance issue when dealing with arrays.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #55
Sidney Cadot wrote:
Mark Gordon wrote:

.... snip ...

That was why I suggested something other than enum. I'm not
sure what else the person who said he wanted enums to be more
special might have meant.


That would have been me. I was aiming for about the same status
for 'enum' types as enumeration types have in Pascal. However,
in C you can of course assign definite integer values to members
of an enum, including duplicates - this complicates matters
considerably.

I guess the only thing that could be done without breaking too
much code is mandating a compiler diagnostic on implicit
conversion of an enum value to an int value. Personally, I think
that would be a good idea.


IMO you cannot correct the existing enum without breaking valid
code. To gain the abilities of the Pascal enumeration requires an
entirely new type. This could be conveniently combined with the
addition of sub-range types, none of which would break old code,
but would provide much additional safety.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 13 '05 #56
Dan Pop wrote:
Mark Gordon <sp******@flash-gordon.me.uk> writes:

.... snip ...

Definitely not. CHAR_BIT==9 may be rare these days, but
CHAR_BIT==16 is not once you start looking at DSP processors
which often don't have the ability to access less that 16
bits (or or) in one operation.


But those are used in freestanding implementations only, and we
ignore such implementations by default, here.


"We" don't, but maybe you do. Such implementations are among the
most important users of C today.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 13 '05 #57
Michael B. wrote:
[Are there any] features that the C specification currently lacks
and which may be included in some future standardization.


The future of C is C++. The question now is,
"Will any future C++ standard adopt the features introduced in C99?"

restricted pointers,
variable-length arrays,
etc.

Nov 13 '05 #58
glen herrmannsfeldt <ga*@ugcs.caltech.edu> wrote:
Morris Dovey wrote:
Michael B. wrote:
I was just thinking about this, specifically wondering if there's any
features that the C specification currently lacks, and which may be
included in some future standardization.
Of course there are. Can you imagine that people will /ever/ stop fixing
things just because they ain't broke?
There was a quote some years ago, I believe by one of the authors of the
original Fortran compiler, though it is hard to verify the source.
Nah, not really hard at all. It was Tony Hoare (now living here in
Cambridge!):

"I don't know what the language of the year 2000 will look like, but
it will be called Fortran."
- C. A. R. Hoare, 1982 Something like: "I don't know what the language of the year 2000 will look like, but it
will be called Fortran." (That is from memory, hopefully it is close.)


Perfect!

Andrew.
Nov 13 '05 #59
Chris Torek wrote:
* triple-&& and triple-|| operators: &&& and ||| with semantics
like the 'and' and 'or' operators in python:

a &&& b ---> if (a) then b else a
a ||| b ---> if (a) then a else b

(I think this is brilliant, and actually useful sometimes).
Besides the syntactic shift (from being parsed as "&& &b" today),
I think it is worth pointing out that if "a" is false, it must compare
equal to 0; so assuming "a &&& b" means "if a then b else a", it
also means "if a then b else 0", which can be expressed today as
"a ? b : 0".

(GCC offers "a ||| b" as "a ?: b", which means "a ? a : b" without
evaluating "a" twice.)


Especially this latter form is quite useful, expressing the idea that
'a' is to be used if it has a non-zero value, else use 'b' as a
fallback. This could be threaded, as in 'a ?: b ?: c'... I'd seriously
hope the next committee would consider this. This actually /is/ useful.
* a way to "bitwise invert" a variable without actually
assigning, complementing "&=", "|=", and friends. The expression "x = ~x" can always be transformed into "x ^= ~0U",
although the constant may need to be written as 0UL, 0ULL,
(uintmax_t)0, or some such. (Using ^= ~(uintmax_t)0 probably
always works, but probably draws warnings on some compilers.)
Ok, then I'd rather stick to 'x=~x', which is clearer. It has always
sort-of annoyed me that the binary operators '+' '-' .... and so on have
assignment forms, while the unary '~' hasn't.
* 'min' and 'max' operators (following gcc: ?< and ?>)

It is also worth noting that Dennis Ritchie's early C compiler(s)
*had* min and max operators, spelled \/ and /\ respectively. They
were dropped, most likely from lack of use.
Funny, I didn't know that - weird syntax.

Personally, I would like to see min/max operators make a comeback. They
are quite often needed in practice, supported by some hardware, and
have clear algebraic foundations (max-plus algebras, and all that).
Someone else asked (further down in the thread) whether some CPUs
might have "min" and "max" instructions. I have never seen precisely
this myself, but many architectures have "synthetic" (and branchless)
min/max sequences -- usually involving the carry bit (many CPUs)
or "set if less than" instructions (MIPS) or the like -- and even
the x86 now has conditional-move. GCC will generate these for the
branch-ful "a < b ? a : b" sequence, e.g.:

int imin(int a, int b) { return a < b ? a : b; }

compiles to, e.g.:

cmpl %eax, %ecx
cmovle %ecx, %eax

when gcc is given the right options (-msse). (V9 sparc also has
conditional move, and ARM has conditional *everything*. :-) )


Interesting. The only processor I've seen that has this is the Philips
Trimedia, an embedded processor optimized for multimedia streaming. It's
a VLIW processors with five parallel instruction units. Branch
prediction failure rollback is quite expensive on these beasts.

Best regards,

Sidney

Nov 13 '05 #60
goose wrote:
* triple-&& and triple-|| operators: &&& and ||| with
semantics like the 'and' and 'or' operators in python:

a &&& b ---> if (a) then b else a
a ||| b ---> if (a) then a else b


[snip]
result = a? b: 0; /* &&& */


ITYM a ? b : a

surely its the same thing ?


Eg.

a() ? b() : a()

is not equivalent to

a() ? b() : 0

if a() has side-effects.

Regards,

Sidney

Nov 13 '05 #61
Dan Pop wrote:
hard to see how you can do this properly without a pile of other stuff, but
if you've got an idea that makes sense advance it here,
oops, advance it in comp.std.c rather than here.


It doesn't make any difference where you advance it: it will get ignored,
anyway.

If you want to promote an idea, either become a committee member


Right-o. How does one become a committee member?
or convince one committee member that it's worth promoting it.


.... My idea was to convice one reader to convince one committee member
that it's worth promoting it.

At least about the stack-fault thing. That really ought to be fixed next
time 'round.

Best regards,

Sidney

Nov 13 '05 #62
pete wrote:
A type which is guaranteed to have at least 32 bits, is a better choice
than one which isn't guaranteed to have at least 32 bits,
for when you need an exactly 32-bit integer type.


Not if the int has 32-bits, and the long has 64 bits.

An other answer is: why? We're not in a casino, tring to improve the
odds. If you need exactly 32-bit integers, nothing besides a 32-bit
integer type will do.

Regards, Sidney

Nov 13 '05 #63
Randy Howard wrote:
In article <3f***********************@news.optusnet.com.au> ,
ne**@ralminNOSPAM.cc says...
I don't like it either, but it would be nice to have a well-defined
way to get packed structs on any implementation. Obviously, because
of the large performance hit, you would only use the packed attribute
where it was absolutely necessary.
Hmm, something like
#pack n
and
#pack default
to reset to whatever the compiler normally does?


Many compiler support something similar to this, via a #pragma pack(n).
I'd prefer something that's a bit more natural-looking though... This
that start with a '#' look like preprocessor-food to me.

Best regards,

Sidney

Nov 13 '05 #64
Randy Howard wrote:
In article <bq**********@news.tudelft.nl>, si****@jigsaw.nl says...
I would be glad when the day arrives when I can start
using them.

What compiler do you use then that you can't use them?


I use gcc, mainly, but the software's users use a variety of systems
(mostly win32, Linux, Sun, HP, AIX, Irix, ...), and I cannot rely on
anything better than a C89 compiler to be available.

If that's the case, then it hardly seems likely that the C0X extensions
which may or may not help you out will be any more useful than any of
the stuff in C99? :-)

Don't get me wrong, this is an interesting thread, but regardless of
the outcome, one has to wonder how many current C programmers will
live long enough to see C99 be available "practically everywhere",
much less whatever comes after it.


We have to think about our grandchildren ... It's bad enough we're
leaving them a world without whales and a polar ice cap, let's not
worsen things by denying them a "|||" operator.

Best regards,

Sidney

Nov 13 '05 #65
James Kuyper wrote:
So, you're going to second this proposal? :-)


No - I think that &&& and ||| would be so rarely used that their
meanings would become trivia questions.


I sort of hoped that role would be reserved for my soon-to-be-proposed
quadruple |||| and &&&& operators.

Ah well.

Best regards,

Sidney

Nov 13 '05 #66
E. Robert Tisdale wrote:
Michael B. wrote:
[Are there any] features that the C specification currently lacks
and which may be included in some future standardization.

The future of C is C++. The question now is,
"Will any future C++ standard adopt the features introduced in C99?"

restricted pointers,
variable-length arrays,
etc.


I would think so. More problems are expected with the C++ committee
deprecating classes, templates, and exceptions. However, the old lesson
that it's never too late to mend your ways should prevail.

The future of C++ is C.

Best regards,

Sidney

Nov 13 '05 #67
On Mon, 01 Dec 2003 18:16:55 GMT
CBFalconer <cb********@yahoo.com> wrote:
Sidney Cadot wrote:
Mark Gordon wrote:

... snip ...

That was why I suggested something other than enum. I'm not
sure what else the person who said he wanted enums to be more
special might have meant.


That would have been me. I was aiming for about the same status
for 'enum' types as enumeration types have in Pascal. However,
in C you can of course assign definite integer values to members
of an enum, including duplicates - this complicates matters
considerably.

I guess the only thing that could be done without breaking too
much code is mandating a compiler diagnostic on implicit
conversion of an enum value to an int value. Personally, I think
that would be a good idea.


IMO you cannot correct the existing enum without breaking valid
code. To gain the abilities of the Pascal enumeration requires an
entirely new type. This could be conveniently combined with the
addition of sub-range types, none of which would break old code,
but would provide much additional safety.


If we are stealing bits from Pascal then I would like a set type with a
full set of set operators including cardinality (number of elements in
set if I remember my sets properly).
--
Mark Gordon
Paid to be a Geek & a Senior Software Developer
Although my email address says spamtrap, it is real and I read it.
Nov 13 '05 #68
Mark Gordon wrote:
If we are stealing bits from Pascal then I would like a set type with a
full set of set operators including cardinality (number of elements in
set if I remember my sets properly).


A hybrid monster is heaving into view....

Integer main(input, output)
{
PrintLn('Hello World')
}

Best regards,
Sidney

Nov 13 '05 #69
Dan Pop wrote:

(snip)
C++ didn't invent // comments, it merely inherited them from C's ancestor,
B. One could argue that they belonged to C since day one ;-)


Does anyone know where /* comments came from?

There is a discussion in another group related to them, as /* is
the end of input signal for some IBM OS's. (starting in column 1).

So /* comments in those OS can't start in column 1 unless the
end of input sequence is changed.

-- glen

Nov 13 '05 #70

On Mon, 1 Dec 2003, CBFalconer wrote:

Dan Pop wrote:
Mark Gordon <sp******@flash-gordon.me.uk> writes:

Definitely not. CHAR_BIT==9 may be rare these days, but
CHAR_BIT==16 is not once you start looking at DSP processors
which often don't have the ability to access less that 16
bits (or or) in one operation.


But those are used in freestanding implementations only, and we
ignore such implementations by default, here.


"We" don't, but maybe you do. Such implementations are among the
most important users of C today.


Nit: "We" do (for values of "we" equivalent to "the general topicality
of comp.lang.c"), but the *C standard* and committees pertaining thereto
don't -- and that's the audience to which Sidney implicitly directed
his post.
Such [free-standing] implementations are indeed among, etc., etc.

:-)
-Arthur

Nov 13 '05 #71
Sidney Cadot <si****@jigsaw.nl> wrote:
Mark Gordon wrote:
If we are stealing bits from Pascal then I would like a set type with a
full set of set operators including cardinality (number of elements in
set if I remember my sets properly).


A hybrid monster is heaving into view....

Integer main(input, output)
{
PrintLn('Hello World')
}

^
You forgot the period. ;-)
--
Irrwahn,
END.
Nov 13 '05 #72
"E. Robert Tisdale" wrote:
Michael B. wrote:
[Are there any] features that the C specification currently lacks
and which may be included in some future standardization.


The future of C is C++. The question now is,
"Will any future C++ standard adopt the features introduced in C99?"

restricted pointers,
variable-length arrays,
etc.

_____________________
/| /| | |
||__|| | Please do not |
/ O O\__ | feed the |
/ \ | Trolls |
/ \ \|_____________________|
/ _ \ \ ||
/ |\____\ \ ||
/ | | | |\____/ ||
/ \|_|_|/ | _||
/ / \ |____| ||
/ | | | --|
| | | |____ --|
* _ | |_|_|_| | \-/
*-- _--\ _ \ | ||
/ _ \\ | / `
* / \_ /- | | |
* ___ c_c_c_C/ \C_c_c_c____________

+-------------------+ .:\:\:/:/:.
| PLEASE DO NOT | :.:\:\:/:/:.:
| FEED THE TROLLS | :=.' - - '.=:
| | '=(\ 9 9 /)='
| Thank you, | ( (_) )
| Management | /`-vvv-'\
+-------------------+ / \
| | @@@ / /|,,,,,|\ \
| | @@@ /_// /^\ \\_\
@x@@x@ | | |/ WW( ( ) )WW
\||||/ | | \| __\,,\ /,,/__
\||/ | | | jgs (______Y______)
/\/\/\/\/\/\/\/\//\/\\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
================================================== ============

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 13 '05 #73
"Sidney Cadot" <si****@jigsaw.nl> wrote:
A hybrid monster is heaving into view....

Integer main(input, output)
{
PrintLn('Hello World')
}


I wouldn't mind some pascal-like declaration forms, that support
cdecl syntax:

main(argc: int; argv: pointer to pointer to char): int
{
linebuf: array 100 of char;
fp: pointer to FILE;

if(argc == 2 && (fp = fopen(argv[1], "r")) != NULL)
{
fgets(linebuf, sizeof linebuf, fp);
fclose(fp);
}
return 0;
}

--
Simon.
Nov 13 '05 #74
>Chris Torek wrote:
(GCC offers "a ||| b" as "a ?: b", which means "a ? a : b" without
evaluating "a" twice.)

In article <news:bq**********@news.tudelft.nl>
Sidney Cadot <si****@jigsaw.nl> writes:Especially this latter form is quite useful, expressing the idea that
'a' is to be used if it has a non-zero value, else use 'b' as a
fallback. This could be threaded, as in 'a ?: b ?: c'... I'd seriously
hope the next committee would consider this. This actually /is/ useful.
It appears in other forms in other languages. For instance, the
Bourne shell has the syntax: ${var-default}, meaning "use the value
of variable foo if the variable exists, otherwise use the default".
(It nests as well: ${NEWSAUTHOR-${USER-`whoami`}}, for instance.)
In C it would have the slight flaw that "compares-equal-to-zero" is
the "unset" value, but C is pretty cavalier about zero being false. :-)

[on min/max instructions and/or conditional moves -- it is not clear
what antecedent "this" referred to:]... The only processor I've seen that has this is the Philips
Trimedia, an embedded processor optimized for multimedia streaming. It's
a VLIW processors with five parallel instruction units. Branch
prediction failure rollback is quite expensive on these beasts.


To short-circuit this thread with another, I think Paul Hseih should
write a lot of hand-coded assembly for such hardware; he might
change his mind about what C code is "efficient". :-) (VLIW can
really strain one's perceptions. In particular, it often becomes
better to do work that may be discarded, than to avoid that work,
because the work takes zero time while the avoidance takes several
cycles. Itanium, with its odd "bundling", can be viewed as a
poor-man's VLIW, too.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 13 '05 #75
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> wrote:
Michael B. wrote:
[Are there any] features that the C specification currently lacks
and which may be included in some future standardization.


The future of C is C++.


Actually, C++ is C's disreputable past.

But you know that, being part of it ;->

Richard
Nov 13 '05 #76
"Malcolm" <ma*****@55bank.freeserve.co.uk> wrote:
"Jack Klein" <ja*******@spamcop.net> wrote:
I could wish that pigs had wings so they could fly, but unless I can
come up with at least some solid engineering plans that showed
feasibility and a favorable cost-benefit ration, I would not expect
anyone to take my wish seriously.


I think there are two to be made for templates. The weak case is that
often it is handy to write a function once with several types of
arguments. For instance swap() naturally lends itself to a template
implementation. So too does mean().

Personally I don't think these cases are common enough to justify a new
language feature, and also involve some subtle problems. For instance
mean() is fine for floats and doubles, but will usually break when fed a
char array, and could easily break with a short.

The stronger case is that the C++ standard template library allows client
code to do away with dynamic memory, and almost to do away with pointers.
[...]


So, rather than implementing a whole new mechanism that takes the
language in another direction, why not try to implement templates
using the existing facilities and see where we are lacking?

The most obvious thing to use is macros -- in fact, I actually use
macros for templates all the time. But one has a difficult time
publishing a library of templates (you know something like a ...
STANDARD TEMPLATE LIBRARY) using such an idea because of the
following:

- The preprocessor does not have its own namespace for its own
symbols, so even something as simple as declaring temporaries and
using them with other variables passed as parameters is walking a
tight rope since the author cannot guarantee that its in a
different name space, and therefore might collide unintentionally.
For example:

#define swap(type,v1,v2) do { \
type tmp; \
tmp = v1; \
v1 = v2; \
v2 = tmp; \
} while (0)

actually doesn't work for something like swap(int,tmp,tmp1); So
using something like $tmp instead would be better -- the idea
being that "$" would be a valid symbol prefix only in the
preprocessor context and be the syntax error you would expect it
to be in ordinary C code.

- There is no type checking of parameters that can be performed at
compile time. Implementing compile time mechanisms as simple as:

assertTypeEqual(a, b, ...)
- Issues a compile time error if all the parameters are not
exactly equal in type.
assertTypeOneOf(a, b, ...)
- Issues error if a is not the same as at least one of the types
of the rest of the parameters.
assertTypeCoercable(a, b, ...)
- Issues error any pair of the set of parameters are not
coercable with each other.

would solve this problem.

- Once cannot perform computations or useful control flow at
preprocessor time. Compare with the Microsoft Assembler's
preprocessor for example. Such features would

#forc $c in "ABCDEF..."
putchar($c)
#endforc

would result in putchar('A'); putchar ('B'); ... etc.

#for $c in 0,1,2,3,4,5
# define $d #eval($c * 2)
printf ("%2d", $c);
#endfor

would result in printf("%2d", 0); print ("%2d", 2); ... etc.

#range(0,5)

would expand as 0,1,2,3,4 and so on.

Such ideas could also take away a lot of the ideas like "lambda
expansion" in languages like Lisp/Scheme.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
Nov 13 '05 #77
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> wrote in message news:<3F**************@jpl.nasa.gov>...
Michael B. wrote:
[Are there any] features that the C specification currently lacks
and which may be included in some future standardization.


The future of C is C++. The question now is,
"Will any future C++ standard adopt the features introduced in C99?"

restricted pointers,
variable-length arrays,
etc.


Well actually they probably will -- and it is in fact *that* which
will spell the final death nail to C99. Any good feature of C99 is
likely to be adopted by the C++ committee while every misfeature (like
defined complex numbers) will simply be ignored. Compiler vendors
(who, of course, make C++ compilers as well) that have passed up C99
comformance because of what pathetically little it did to try to move
forward the cause of the C language, will more likely adopt the C++
standard and just leave the remaining C99 nonsense in the trash bin
where it belongs.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
Nov 13 '05 #78
qe*@pobox.com (Paul Hsieh) wrote:
Well actually they probably will -- and it is in fact *that* which
will spell the final death nail to C99. Any good feature of C99 is
likely to be adopted by the C++ committee


Can't be. Not needing to cast void pointers left, right and everywhere
is a very good feature of C, which will always be missing from C++.
Ditto most other features which make C a sleek, useful language and C++
a humungous monstrum.

Richard
Nov 13 '05 #79
Paul Hsieh wrote:
spell the final death nail


I think you mean "sound the final death knell"

--
pete
Nov 13 '05 #80
In <bq**********@news.tudelft.nl> Sidney Cadot <si****@jigsaw.nl> writes:
Dan Pop wrote:
hard to see how you can do this properly without a pile of other stuff, but
if you've got an idea that makes sense advance it here,

oops, advance it in comp.std.c rather than here.


It doesn't make any difference where you advance it: it will get ignored,
anyway.

If you want to promote an idea, either become a committee member


Right-o. How does one become a committee member?


As I understand it, it's a matter of having enough money and free time
on your hands.
or convince one committee member that it's worth promoting it.


... My idea was to convice one reader to convince one committee member
that it's worth promoting it.

At least about the stack-fault thing. That really ought to be fixed next
time 'round.


Spend more time on comp.std.c and you won't be so optimistic. There are
huge loopholes in the current standard, inherited from the old standard
and no one wants to do anything to fix them. "It's not a problem in
practice" is the usual lame excuse.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #81
In <3F***************@yahoo.com> CBFalconer <cb********@yahoo.com> writes:
Dan Pop wrote:
Mark Gordon <sp******@flash-gordon.me.uk> writes:
... snip ...
>
> Definitely not. CHAR_BIT==9 may be rare these days, but
> CHAR_BIT==16 is not once you start looking at DSP processors
> which often don't have the ability to access less that 16
> bits (or or) in one operation.


But those are used in freestanding implementations only, and we
ignore such implementations by default, here.

^^^^^^^^^^^^^^^^"We" don't, but maybe you do. Such implementations are among the
most important users of C today.


Yes, we do. All the time we discuss about the main function or include
standard library functions in our solutions we implicitly ignore
freestanding implementations, where main() need not have any special
semantics and where no standard library functions may be available.

We *have* to ignore freestanding implementations, because they're
too loosely covered by the standard. If you disagree, please post
a C program (it doesn't need to do anything at all) that is portable
to *any* freestanding implementation.

And don't forget to engage your brain next time you want to object to
one of my posts.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #82
Mark McIntyre <ma**********@spamcop.net> wrote in message news:<h9********************************@4ax.com>. ..
....
*shrug*. I understand your point, but when in implementation-dependent
territory, its quite immaterial what ISO requires, its never going to
safely port anyway so abandon all hope, ye who enter here....


As a practical matter, implementation-dependent is not all-or-nothing.
There are degrees of implmentation-dependence; some constructs impede
portability more than others (and that includes many strictly
conforming constructs, since not all implementation are fully
conforming). Relying on 'int' being exactly 32 bits restricts the
portability of your code to a certain set of implementations. Relying
upon 'long' being exactly 32 bits restricts the portability of your
code to a different, overlapping set of implementations. It's
legitimate to worry about which of those two sets is bigger.

It's better to write code that checks for INT32_MAX and uses int32_t,
relying a supplemental "inttypes.h" if necessary until you have access
to a true C99 implementation. However, it's not completely wrong to
use the other approach.
Nov 13 '05 #83
Sidney Cadot <si****@jigsaw.nl> wrote in message news:<bq**********@news.tudelft.nl>...
goose wrote:
>* triple-&& and triple-|| operators: &&& and ||| with
> semantics like the 'and' and 'or' operators in python:
>
> a &&& b ---> if (a) then b else a
> a ||| b ---> if (a) then a else b

[snip]

result = a? b: 0; /* &&& */

ITYM a ? b : a

surely its the same thing ?


Eg.

a() ? b() : a()

is not equivalent to

a() ? b() : 0

if a() has side-effects.


no, but if a and b are not macros which expand to a() and b(), then

a ? b : 0

is identical to

a ? b : a

<nit>
the example code above did not actually state whether or not
macros were used, or if there were any side-effects.

it *did* however, use a and b, and not a() and b().

hand
goose,
not busy today at all.
Nov 13 '05 #84
Sidney Cadot <si****@jigsaw.nl> wrote:
Michael B. wrote:
I was just thinking about this, specifically wondering if there's
any features that the C specification currently lacks, and which
may be included in some future standardization.
I think C99 has come a long way to fix the most obvious problems in
C89 (and its predecessors).


It has? I can't think of a single feature in C99 that would come as
anything relevant in any code I have ever written or will ever write
in the C with the exception of "restrict" and //-style comments.
There are a number of features in C99 that I will steer away from if
this issue ever comes up.
[...] I for one would be happy if more compilers would
fully start to support C99, It will be a good day when I can actually
start to use many of the new features without having to worry about
portability too much, as is the current situation.
I don't think that day will ever come. In its totallity C99 is almost
completely worthless in real world environments. Vendors will be
smart to pick up restrict and few of the goodies in C99 and just stop
there.
There's always some things that could be improved of course. My
personal wish-list would include (in no particular order):

* mandatory support for fixed-width integers (in C99, this is
optional).
Hmm ... no, if you can determine that a platform does not suppose such
a fixed-width type at compile time, that's probably good enough.
* support for a "packed" attribute to structs, guaranteeing that no
padding occurs.
Indeed, this is something I use on the x86 all the time. The problem
is that on platforms like UltraSparc or Alpha, this will either
inevitably lead to BUS errors, or extremely slow performing code.

If instead, the preprocessor were a lot more functional, then you
could simply extract packed offsets from a list of declarations and
literally plug them in as offsets into a char[] and do the slow memcpy
operations yourself.
* upgraded status of enum types (they are currently quite
interchangeable with ints); deprecation of implicit casts from
int to enum (perhaps supported by a mandatory compiler warning).
I agree. Enums, as far as I can tell, are almost useless from a
compiler assisted code integrity point of view because of the
automatic coercion between ints and enums. Its almost not worth the
bothering to ever using an enum for any reason because of it.
* a clear statement concerning the minimal level of active function
calls invocations that an implementation needs to support.
Currently, recursive programs will stackfault at a certain point,
and this situation is not handled satisfactorily in the standard
(it is not adressed at all, that is), as far as I can tell.
That doesn't seem possible. The amount of "stack" that an
implementation might use for a given function is clearly not easy to
define. Better to just leave this loose.
* a library function that allows the retrieval of the size of a memory
block previously allocated using "malloc"/"calloc"/"realloc" and
friends.
There's a lot more that you can do as well. Such as a tryexpand()
function which works like realloc except that it performs no action
except returning with some sort of error status if the block cannot be
resized without moving its base pointer. Further, one would like to
be able to manage *multiple* heaps, and have a freeall() function --
it would make the problem of memory leaks much more manageable for
many applications. It would almost make some cases enormously faster.
* a #define'd constant in stdio.h that gives the maximal number of
characters that a "%p" format specifier can emit. Likewise, for
other format specifiers such as "%d" and the like.

* a printf format specifier for printing numbers in base-2.
Ah -- the kludge request. Rather than adding format specifiers one at
a time, why not instead add in a way of being able to plug in
programmer-defined format specifiers? I think people in general would
like to use printf for printing out more than just the base types in a
collection of just a few formats defined at the whims of some 70s UNIX
hackers. Why not be able to print out your data structures, or
relevant parts of them as you see fit?
* I think I would like to see a real string-type as a first-class
citizen in C, implemented as a native type. But this would open
up too big a can of worms, I am afraid, and a good case can be
made that this violates the principles of C too much (being a
low-level language and all).
The problem is that real string handling requires memory handling.
The other primitive types in C are flat structures that are fixed
width. You either need something like C++'s constructor/destructor
semantics or automatic garbage collection otherwise you're going to
have some trouble with memory leaking.

With the restrictions of the C language, I think you are going to find
it hard to have even a language implemented primitive that takes you
anywhere beyond what I've done with the better string library, for
example (http://bstring.sf.net). But even with bstrlib, you need to
explicitely call bdestroy to clean up your bstrings.

I'd be all for adding bstrlib to the C standard, but I'm not sure its
necessary. Its totally portable and freely downloadable, without much
prospect for compiler implementors to improve upon it with any native
implementations, so it might just not matter.
* Normative statements on the upper-bound worst-case asymptotic
behavior of things like qsort() and bsearch() would be nice.
Yeah, it would be nice to catch up to where the C++ people have gone
some years ago.
O(n*log(n)) for number-of-comparisons would be fine for qsort,
although I believe that would actually preclude a qsort()
implementation by means of the quicksort algorithm :-)
Anything that precludes the implementation of an actual quicksort
algorithm is a good thing. Saying Quicksort is O(n*log(n)) most of
the time is like saying Michael Jackson does not molest most of the
children in the US.
* mandatory constants for many things that currently need to
be tested by autoconf and similar tools, e.g. endianness.
A good idea.
* deprecate trigraphs. Let's end the madness once and for all.
Let's not and say we did.
* a reliable and easy way to walk over all integers in a certain
interval, including the MAX value for that type, by means of a
for loop; eg., currently

for(unsigned i=0;i<=UINT_MAX;i++) ...

doesn't work as intended.
Hmmm ... its not like you can't construct a loop to do this correctly,
so I'm not sure you need a language extension just for this. I think
this is too marginal.
* a "reverse comma" type expression, for example denoted by
a reverse apastrophe, where the leftmost value is the value
of the entire expression, but the right-hand side is also
guaranteed to be executed.
This seems too esoteric.
* triple-&& and triple-|| operators: &&& and ||| with semantics
like the 'and' and 'or' operators in python:

a &&& b ---> if (a) then b else a
a ||| b ---> if (a) then a else b

(I think this is brilliant, and actually useful sometimes).
Hmmm ... why not instead have ordinary operator overloading? While
this is sometimes a useful shorthand, I am sure that different
applications have different list cutesy compactions that would be
worth while instead of the one above.
* a way to "bitwise invert" a variable without actually
assigning, complementing "&=", "|=", and friends.
Is a ~= a really that much of a burden to type?
* 'min' and 'max' operators (following gcc: ?< and ?>)
As I mentioned above, you might as well have operator overloading instead.
* a div and matching mod operator that round to -infinity,
to complement the current less useful semantics of rounding
towards zero.
Well ... but this is the very least of the kinds of arithmetic operator
extensions that one would want. A widening multiply operation is
almost *imperative*. It always floors me that other languages are not
picking this up. Nearly every modern microprocessor in existence has
a widening multiply operation -- because the CPU manufacturer *KNOW*
its necessary. And yet its not accessible from any language. Probably
because most languages have been written on top of C or C++. And what
about a simple carry capturing addition?
Personally, I don't think it would be a good idea to have templates
in C, not even simple ones. This is bound to have quite complicated
semantics that I would not like to internalize.


Right -- this would just be making C into C++. Why not instead
dramatically improve the functionality of the preprocessor so that the
macro-like cobblings we put together in place of templates are
actually good for something? I've posted elsewhere about this, so I
won't go into details.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
Nov 13 '05 #85
In <8b**************************@posting.google.com > ku****@wizard.net (James Kuyper) writes:
It's better to write code that checks for INT32_MAX and uses int32_t, ^^^^^^^^^^^relying a supplemental "inttypes.h" if necessary until you have access
to a true C99 implementation.
That's open to debate. Hiding the real type behind a typedef has its own
costs in terms of readability and maintainabilty and it's more bug prone
than using a well defined type. It's trivial to check the assumption at
compile time, so there is no risk of generating broken code.
However, it's not completely wrong to use the other approach.


This is true, regardless of which is the other approach ;-)

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #86
Dan Pop wrote:
Right-o. How does one become a committee member?
As I understand it, it's a matter of having enough money and free time
on your hands.


Ah well, won't be joining anytime soon then.
At least about the stack-fault thing. That really ought to be fixed next
time 'round.


Spend more time on comp.std.c and you won't be so optimistic. There are
huge loopholes in the current standard, inherited from the old standard
and no one wants to do anything to fix them. "It's not a problem in
practice" is the usual lame excuse.


I never understood why people get so worked up about practice. It's
clearly an overrated part of reality.

Best regards,

Sidney

Nov 13 '05 #87
goose wrote:
no, but if a and b are not macros which expand to a() and b(), then

a ? b : 0

is identical to

a ? b : a

<nit>
the example code above did not actually state whether or not
macros were used, or if there were any side-effects.

it *did* however, use a and b, and not a() and b().


Well, I used a and b as stand-ins for "any two expressions".
By the way, got any funny looks talking to people today?

(You forgot the </nit>)

Best regards,

Sidney

Nov 13 '05 #88
qe*@pobox.com (Paul Hsieh) writes:
Sidney Cadot <si****@jigsaw.nl> wrote:

[...]
* support for a "packed" attribute to structs, guaranteeing that no
padding occurs.


Indeed, this is something I use on the x86 all the time. The problem
is that on platforms like UltraSparc or Alpha, this will either
inevitably lead to BUS errors, or extremely slow performing code.

If instead, the preprocessor were a lot more functional, then you
could simply extract packed offsets from a list of declarations and
literally plug them in as offsets into a char[] and do the slow memcpy
operations yourself.


Obviously an implementation of packed structures is useless if it
leads to bus errors.

There's ample precedent in other languages (Pascal and Ada at least)
for packed structures. Typically the members are aligned on byte
boundaries rather than on the most efficient alignment boundaries.
The generated code just has to deal with any misalignment; this
shouldn't be all that difficult. (In the worst case, the compiler can
just generate calls to memcpy().) Users need to be aware that they're
trading size for performance.

One potential problem (assume 4-byte ints, normally requiring 4-byte
alignment):

_Packed struct { /* or whatever syntax you like */
char c; /* offset 0, size 1 */
int i; /* offset 1, size 4 */
} packed_obj;

You can't sensible take the address of packed_obj.i. A function that
takes an "int*" argument will likely die if you give it a misaligned
pointer (unless you want to allow _Packed as an attribute for function
arguments). The simplest approach would be to forbid taking the
address of a member of a packed structure (think of the members as fat
bit fields). Another possibility (ugly but perhaps useful) is to make
the address of a member of a packed field yield a void*.
* upgraded status of enum types (they are currently quite
interchangeable with ints); deprecation of implicit casts from
int to enum (perhaps supported by a mandatory compiler warning).


I agree. Enums, as far as I can tell, are almost useless from a
compiler assisted code integrity point of view because of the
automatic coercion between ints and enums. Its almost not worth the
bothering to ever using an enum for any reason because of it.


I don't think enums can be repaired without breaking tons of existing
code. And they are useful as currently defined for defining names for
a number of distinct integer values. If you want Pascal-like
enumeration types, you'd need a new construct -- but I think having
two distinct kinds of enumeration types would be too ugly for new
users.
* a clear statement concerning the minimal level of active function
calls invocations that an implementation needs to support.
Currently, recursive programs will stackfault at a certain point,
and this situation is not handled satisfactorily in the standard
(it is not adressed at all, that is), as far as I can tell.


That doesn't seem possible. The amount of "stack" that an
implementation might use for a given function is clearly not easy to
define. Better to just leave this loose.


Agreed. The limit on call depth is typically determined by the amount
of available memory, something a compiler implementer can't say much
about. You could sensibly add a call depth clause to the Translation
Limits section (C99 5.2.4.1); that would the implementation to handle
at least one program with a call depth of N, but wouldn't really
guarantee anything in general.

[...]
* a #define'd constant in stdio.h that gives the maximal number of
characters that a "%p" format specifier can emit. Likewise, for
other format specifiers such as "%d" and the like.

* a printf format specifier for printing numbers in base-2.


Ah -- the kludge request. Rather than adding format specifiers one at
a time, why not instead add in a way of being able to plug in
programmer-defined format specifiers? I think people in general would
like to use printf for printing out more than just the base types in a
collection of just a few formats defined at the whims of some 70s UNIX
hackers. Why not be able to print out your data structures, or
relevant parts of them as you see fit?


Well, you can do that with the "%s" specifier, as long as you've
defined a function that returns an image string for a value of your
type (with all the complications of functions returning dynamic
strings).

I think that base-2 literals (0b11001001) and a corresponding printf
format specifier would be sensible additions.

[...]
* a "reverse comma" type expression, for example denoted by
a reverse apastrophe, where the leftmost value is the value
of the entire expression, but the right-hand side is also
guaranteed to be executed.


This seems too esoteric.


And you'd need a trigraph (and probably a digraph) for the reverse
apostrophe character.

If you really need such a thing, you can fake it:

( tmp = LHS, RHS, tmp )
* triple-&& and triple-|| operators: &&& and ||| with semantics
like the 'and' and 'or' operators in python:

a &&& b ---> if (a) then b else a
a ||| b ---> if (a) then a else b

(I think this is brilliant, and actually useful sometimes).


Hmmm ... why not instead have ordinary operator overloading? While
this is sometimes a useful shorthand, I am sure that different
applications have different list cutesy compactions that would be
worth while instead of the one above.
* a way to "bitwise invert" a variable without actually
assigning, complementing "&=", "|=", and friends.


Is a ~= a really that much of a burden to type?


I think you mean "a = ~a".
* 'min' and 'max' operators (following gcc: ?< and ?>)


As I mentioned above, you might as well have operator overloading instead.


Most languages that provide operator overloading restrict it to
existing operator symbols. If you want "min" and "max" for int, there
aren't any spare operator symbols you can use. If you want to allow
overloading for arbitrary symbols (which some languages do), you'll
need to decide how and whether the user can define precedence for the
new operators. And of course it would provide rich fodder for the
IOCCC.

[...]
Personally, I don't think it would be a good idea to have templates
in C, not even simple ones. This is bound to have quite complicated
semantics that I would not like to internalize.


Right -- this would just be making C into C++. Why not instead
dramatically improve the functionality of the preprocessor so that the
macro-like cobblings we put together in place of templates are
actually good for something? I've posted elsewhere about this, so I
won't go into details.


Hmm. I'm not sure that making the preprocessor *more* powerful is
such a good idea. It's too easy to abuse as it is:

#include <stdio.h>
#define SIX 1+5
#define NINE 8+1
int main(void)
{
printf("%d * %d = %d\n", SIX, NINE, SIX * NINE);
return 0;
}

If you can improve the preprocessor without making it even more
dangerous, that's great. (I don't think I've see your proposal.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
(Note new e-mail address)
Nov 13 '05 #89
Paul Hsieh wrote:
Sidney Cadot <si****@jigsaw.nl> wrote:
I think C99 has come a long way to fix the most obvious problems in
C89 (and its predecessors). It has? I can't think of a single feature in C99 that would come as
anything relevant in any code I have ever written or will ever write
in the C with the exception of "restrict" and //-style comments.
For programming style, I think loop-scoped variable declarations ae a
big win. Then there is variable sized array, and complex numbers... I'd
really use all this (and more) quite extensively in day-to-day work.
[...] I for one would be happy if more compilers would
fully start to support C99, It will be a good day when I can actually
start to use many of the new features without having to worry about
portability too much, as is the current situation. I don't think that day will ever come. In its totallity C99 is almost
completely worthless in real world environments. Vendors will be
smart to pick up restrict and few of the goodies in C99 and just stop
there.
Want to take a bet...?
* support for a "packed" attribute to structs, guaranteeing that no
padding occurs.


Indeed, this is something I use on the x86 all the time. The problem
is that on platforms like UltraSparc or Alpha, this will either
inevitably lead to BUS errors, or extremely slow performing code.


Preventing the former is the compiler's job; as for the latter, the
alternative is to do struct unpacking/unpacking by hand. Did that, and
didn't like it for one bit. And of course it's slow, but I need the
semantics.
If instead, the preprocessor were a lot more functional, then you
could simply extract packed offsets from a list of declarations and
literally plug them in as offsets into a char[] and do the slow memcpy
operations yourself.
This would violate the division between preprocessor and compiler too
much (the preprocessor would have to understand quite a lot of C semantics).
* upgraded status of enum types (they are currently quite
interchangeable with ints); deprecation of implicit casts from
int to enum (perhaps supported by a mandatory compiler warning).

I agree. Enums, as far as I can tell, are almost useless from a
compiler assisted code integrity point of view because of the
automatic coercion between ints and enums. Its almost not worth the
bothering to ever using an enum for any reason because of it.


Yes.
* a clear statement concerning the minimal level of active function
calls invocations that an implementation needs to support.
Currently, recursive programs will stackfault at a certain point,
and this situation is not handled satisfactorily in the standard
(it is not adressed at all, that is), as far as I can tell. That doesn't seem possible. The amount of "stack" that an
implementation might use for a given function is clearly not easy to
define. Better to just leave this loose.
It's not easy to define, that's for sure. But to call into recollection
a post from six weeks ago:

#include <stdio.h>

/* returns n! modulo 2^(number of bits in an unsigned long) */
unsigned long f(unsigned long n)
{
return (n==0) ? 1 : f(n-1)*n;
}

int main(void)
{
unsigned long z;
for(z=1;z!=0;z*=2)
{
printf("%lu %lu\n", z, f(z));
fflush(stdout);
}
return 0;
}

....This is legal C (as per the Standard), but it overflows the stack on
any implementation (which is usually a sumptom of UB). Why is there no
statement in the standard that even so much as hints at this?
* a library function that allows the retrieval of the size of a memory
block previously allocated using "malloc"/"calloc"/"realloc" and
friends.


There's a lot more that you can do as well. Such as a tryexpand()
function which works like realloc except that it performs no action
except returning with some sort of error status if the block cannot be
resized without moving its base pointer. Further, one would like to
be able to manage *multiple* heaps, and have a freeall() function --
it would make the problem of memory leaks much more manageable for
many applications. It would almost make some cases enormously faster.


But this is perhaps territory that the Standard should steer clear of,
more like something a well-written and dedicated third-party library
could provide.
* a #define'd constant in stdio.h that gives the maximal number of
characters that a "%p" format specifier can emit. Likewise, for
other format specifiers such as "%d" and the like.

* a printf format specifier for printing numbers in base-2. Ah -- the kludge request.
I'd rather see this as filling in a gaping hole.
Rather than adding format specifiers one at
a time, why not instead add in a way of being able to plug in
programmer-defined format specifiers?
Because that's difficult to get right (unlike a proposed binary output
form).
I think people in general would
like to use printf for printing out more than just the base types in a
collection of just a few formats defined at the whims of some 70s UNIX
hackers. Why not be able to print out your data structures, or
relevant parts of them as you see fit?
The %x format specifier mechanism is perhaps not a good way to do this,
if only because it would only allow something like 15 extra output formats.
* I think I would like to see a real string-type as a first-class
citizen in C, implemented as a native type. But this would open
up too big a can of worms, I am afraid, and a good case can be
made that this violates the principles of C too much (being a
low-level language and all).


The problem is that real string handling requires memory handling.
The other primitive types in C are flat structures that are fixed
width. You either need something like C++'s constructor/destructor
semantics or automatic garbage collection otherwise you're going to
have some trouble with memory leaking.


A very simple reference-counting implementation would suffice. But yes,
it would not rhyme well with the rest of C.
With the restrictions of the C language, I think you are going to find
it hard to have even a language implemented primitive that takes you
anywhere beyond what I've done with the better string library, for
example (http://bstring.sf.net). But even with bstrlib, you need to
explicitely call bdestroy to clean up your bstrings.

I'd be all for adding bstrlib to the C standard, but I'm not sure its
necessary. Its totally portable and freely downloadable, without much
prospect for compiler implementors to improve upon it with any native
implementations, so it might just not matter.
* Normative statements on the upper-bound worst-case asymptotic
behavior of things like qsort() and bsearch() would be nice.


Yeah, it would be nice to catch up to where the C++ people have gone
some years ago.


I don't think it is a silly idea to have some consideration for
worst-case performance in the standard, especially for algorithmic
functions (of which qsort and bsearch are the most prominent examples).
O(n*log(n)) for number-of-comparisons would be fine for qsort,
although I believe that would actually preclude a qsort()
implementation by means of the quicksort algorithm :-)

Anything that precludes the implementation of an actual quicksort
algorithm is a good thing. Saying Quicksort is O(n*log(n)) most of
the time is like saying Michael Jackson does not molest most of the
children in the US.

* a "reverse comma" type expression, for example denoted by
a reverse apastrophe, where the leftmost value is the value
of the entire expression, but the right-hand side is also
guaranteed to be executed.


This seems too esoteric.


Why is it any more esoteric than having a comma operator?
* triple-&& and triple-|| operators: &&& and ||| with semantics
like the 'and' and 'or' operators in python:

a &&& b ---> if (a) then b else a
a ||| b ---> if (a) then a else b

(I think this is brilliant, and actually useful sometimes).


Hmmm ... why not instead have ordinary operator overloading?


I'll provide three reasons.

1) because it is something completely different
2) because it is quite unrelated (I don't get the 'instead')
3) because operator overloading is mostly a bad idea, IMHO
While
this is sometimes a useful shorthand, I am sure that different
applications have different list cutesy compactions that would be
worth while instead of the one above.
.... I'd like to see them. &&& is a bit silly (it's fully equivalent to
"a ? b : 0") but ||| (or ?: in gcc) is actually quite useful.
* a way to "bitwise invert" a variable without actually
assigning, complementing "&=", "|=", and friends.


Is a ~= a really that much of a burden to type?


It's more a strain on the brain to me, why there are coupled
assignment/operators for neigh all binary operators, but not for this
unary one.
* 'min' and 'max' operators (following gcc: ?< and ?>)


As I mentioned above, you might as well have operator overloading instead.


Now I would ask you: which existing operator would you like to overload
for, say, integers, to mean "min" and "max" ?
* a div and matching mod operator that round to -infinity,
to complement the current less useful semantics of rounding
towards zero. Well ... but this is the very least of the kinds of arithmetic operator
extensions that one would want. A widening multiply operation is
almost *imperative*. It always floors me that other languages are not
picking this up. Nearly every modern microprocessor in existence has
a widening multiply operation -- because the CPU manufacturer *KNOW*
its necessary. And yet its not accessible from any language.
....It already is available in C, given a good-enough compiler. Look at
the code gcc spits out when you do:

unsigned long a = rand();
unsigned long b = rand();

unsigned long long c = (unsigned long long)a * b;
Probably because most languages have been written on top of C or C++.
And what about a simple carry capturing addition?
Many languages exists where this is possible, they are called
"assembly". There is no way that you could come up with a well-defined
semantics for this.

Did you know that a PowerPC processor doesn't have a shift-right where
you can capture the carry bit in one instruction? Silly but no less true.
Personally, I don't think it would be a good idea to have templates
in C, not even simple ones. This is bound to have quite complicated
semantics that I would not like to internalize.

Right -- this would just be making C into C++. Why not instead
dramatically improve the functionality of the preprocessor so that the
macro-like cobblings we put together in place of templates are
actually good for something? I've posted elsewhere about this, so I
won't go into details.


This would intertwine the preprocessor and the compiler; the
preprocessor would have to understand a great deal more about C
semantics than in currently does (almost nothing).

Best regards,

Sidney
Nov 13 '05 #90
Paul Hsieh wrote:
Sidney Cadot <si****@jigsaw.nl> wrote:
.... snip ...
* upgraded status of enum types (they are currently quite
interchangeable with ints); deprecation of implicit casts from
int to enum (perhaps supported by a mandatory compiler warning).


I agree. Enums, as far as I can tell, are almost useless from a
compiler assisted code integrity point of view because of the
automatic coercion between ints and enums. Its almost not worth the
bothering to ever using an enum for any reason because of it.


On the contrary they are extremely useful in defining a series of
constants that must follow each other, and yet allow easy
revision. Compare:

#define one 1
#define two (one + 1)
#define three (two + 1)
....
#define last (something + 1)

with

enum (one = 1, two, three, .... last};

and compare the effort (and potential error) of injecting
twoandahalf in each.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 13 '05 #91
pete wrote:
Paul Hsieh wrote:
spell the final death nail


I think you mean "sound the final death knell"


You have pounded home the final nail while watching him writhe in
his final death throes. All of which is finally fine with me.
Sedulously eschew sadistic obfuscation. :-)

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 13 '05 #92
On Sun, 30 Nov 2003, Sidney Cadot wrote:
I think C99 has come a long way to fix the most obvious problems in C89
(and its predecessors). I for one would be happy if more compilers would
fully start to support C99, It will be a good day when I can actually
start to use many of the new features without having to worry about
portability too much, as is the current situation.

"Arthur J. O'Dwyer" <aj*@nospam.andrew.cmu.edu> wrote: Agreed. Although besides the mixing of declarations and statements,
I can't think of any C99 features I *use* that are lacking in C90.


Hmm... in C99 I can do

char symbols [128] = { ['*'] = 1, ['/'] = 2, ['+'] = 3, ['-'] = 4, ... };

or

struct
{
char *expr;
int value;
} lexer ['z' - 'a'] = { ['b' - 'a'] = { "[a-zA-Z]", 0 }, ... };

or

struct flag
{
bool one;
bool other;
};

struct flag initFlag =
{
.one = false,
.other = true
};
(at global scope)

or

FILE *fp;
#define PRINTHIS(...) fprintf (fp, __VA_ARGS__)

or

#define varIF(...) if (__VA_ARGS__) {

or

#define VERIFY(...) { int table[] = { __VA_ARGS__, 1 }; printf("%d",table);

what's the equivalent in C89?

Nov 13 '05 #93
In message <ln************@nuthaus.mib.org>
Keith Thompson <ks***@mib.org> wrote:
One potential problem (assume 4-byte ints, normally requiring 4-byte
alignment):

_Packed struct { /* or whatever syntax you like */
char c; /* offset 0, size 1 */
int i; /* offset 1, size 4 */
} packed_obj;

You can't sensible take the address of packed_obj.i. A function that
takes an "int*" argument will likely die if you give it a misaligned
pointer (unless you want to allow _Packed as an attribute for function
arguments). The simplest approach would be to forbid taking the
address of a member of a packed structure (think of the members as fat
bit fields).


The simplest way is to also treat _Packed as a type qualifier, much like
const.

&packed_obj.i would be of type _Packed int *; it wouldn't be possible
to assign it to an int *. For CPUs which don't allow unaligned access, the
concept of a _Packed (ie unaligned) pointer is useful, probably more so than
unaligned structures, as it allows the C programmer to easily read an
unaligned value from any raw, unaligned data.

That's the way the _Packed implementation I've seen works.

The one wrinkle is that the _Packed-ness has to attach to the struct tag in
that declaration, to ensure struct type compatibility. Not an issue in your
example, but it is if the struct was named. Also all sub-structures of
_Packed structures must themselves be _Packed.

I would be in favour of standardising _Packed. Even if you didn't totally
standardise _Packed structure layout, the standardisation of the actual
syntax and type rules would be worthwhile.

--
Kevin Bracey, Principal Software Engineer
Tematic Ltd Tel: +44 (0) 1223 503464
182-190 Newmarket Road Fax: +44 (0) 1223 503458
Cambridge, CB5 8HE, United Kingdom WWW: http://www.tematic.com/
Nov 13 '05 #94
In message <8b**************************@posting.google.com >
ku****@wizard.net (James Kuyper) wrote:
"Arthur J. O'Dwyer" <aj*@nospam.andrew.cmu.edu> wrote in message news:<Pi**********************************@unix44. andrew.cmu.edu>...
...
is easier for me to grasp. And I think (but this is just IMH
and uneducated O) that C++ compilers need a lot of extra baggage
to deal with constant "consts," and I wouldn't want to foist all
that on C compilers.


I'm curious - why do you think that? I don't know that you're wrong,
but I can't think of any reason why it would be a significant cost.


Nah, it's dead cheap. Only about 15 lines in my C++ compiler. You just need
an extra field in your "Variable" objects containing the "known" constant
value from the initialiser, if any, and you substitute that in every time the
variable's value is referenced.

It would be just as easy to do this as an optimisation for a C compiler as
well, if it weren't for the requirement to still flag up the non-constant
constraint violations. Also, tentative definitions slightly confuse things,
in that a const int may become known later.

--
Kevin Bracey, Principal Software Engineer
Tematic Ltd Tel: +44 (0) 1223 503464
182-190 Newmarket Road Fax: +44 (0) 1223 503458
Cambridge, CB5 8HE, United Kingdom WWW: http://www.tematic.com/
Nov 13 '05 #95

On Wed, 3 Dec 2003, Lorenzo Villari wrote:

On Sun, 30 Nov 2003, Sidney Cadot wrote:
I think C99 has come a long way to fix the most obvious problems in C89
(and its predecessors). I for one would be happy if more compilers would
fully start to support C99, It will be a good day when I can actually
start to use many of the new features without having to worry about
portability too much, as is the current situation.

"Arthur J. O'Dwyer" <aj*@nospam.andrew.cmu.edu> wrote:
Agreed. Although besides the mixing of declarations and statements,
I can't think of any C99 features I *use* that are lacking in C90.


Hmm... in C99 I can do


[and then at the end asks] what's the equivalent in C89? char symbols [128] = { ['*'] = 1, ['/'] = 2, ['+'] = 3, ['-'] = 4, ... };
This is reasonable; it's just not something I do a lot.

char symbols[128] = {0};
symbols['*'] = 1;
symbols['/'] = 2;
symbols['+'] = 3;
...
or
char ops[] = {'*', '/', '+', '-', ...};
char symbols[128] = {0};
int i;
for (i=0; i < sizeof ops; ++i)
symbols[ops[i]] = i+1;

or

struct
{
char *expr;
int value;
} lexer ['z' - 'a'] = { ['b' - 'a'] = { "[a-zA-Z]", 0 }, ... };
No reasonable (portable) C equivalent that I can think of.
I'm not even sure what some of those expressions are *meant*
to do -- aren't you making the implicit assumption that ('b'-'a')
is equal to 1? So why not write 1? Why not write 25 instead of
('z' - 'a'), and save yourself the whole ASCII assumption?
Once you've gotten that far, it's trivial to re-write the code
in either the way I wrote above, or as a C89-style initializer
(simply drop the array indices).
or

struct flag
{
bool one;
bool other;
};
struct flag
{
int one;
int other;
};

which I tend to do, even in C++, which has had 'bool' longer than
C, I think (although I do write methods returning 'bool' when it
makes sense -- I guess the 'int' thing is just a habit at this point).
struct flag initFlag =
{
.one = false,
.other = true
};
(at global scope)
struct flag initFlag = { 0, 1 };

:-) I see how the C99 way is better, yes.

FILE *fp;
#define PRINTHIS(...) fprintf (fp, __VA_ARGS__)
#include <stdio.h>
#include <stdarg.h>
FILE *fp;
void PRINTHIS(const char *s, ...)
{
va_list ap;
va_start(ap, s);
vfprintf(fp, s, ap);
va_end(ap);
}

The "C89 way" even does some typechecking on the first
parameter! :-)

#define varIF(...) if (__VA_ARGS__) {
#define varIF(x) if (x) {
or
#define varIF(parenthesized) if parenthesized {
or
#undef varIF /* why use such a thing in the first place? */

#define VERIFY(...) { int table[] = { __VA_ARGS__, 1 }; printf("%d",table);


Huh? Here, there's a mismatch in the format specifier for
printf(); the variadic portion of the macro arguments can only
take on 'int' values; called with no arguments, the macro will
not even compile; the macro is not brace-balanced (missing one
closing } brace); and I have no idea what its point is.
But certainly it can't be compiled with a C89 compiler, either!

my $.02,
-Arthur
Nov 13 '05 #96
"Arthur J. O'Dwyer" <aj*@nospam.andrew.cmu.edu> wrote:

struct flag
{
bool one;
bool other;
};
struct flag
{
int one;
int other;
};

which I tend to do, even in C++, which has had 'bool' longer than
C, I think (although I do write methods returning 'bool' when it
makes sense -- I guess the 'int' thing is just a habit at this point).
struct flag initFlag =
{
.one = false,
.other = true
};
(at global scope)


struct flag initFlag = { 0, 1 };

:-) I see how the C99 way is better, yes.


Ok... but what if

struct problem
{
bool one;
bool other;
int someother;
char anyway[80];
float thank;
void *you;
double very_much;
};

struct flag initFlag =
{
.thank = 5.4,
.very_much = 4.5
};

and initFlag is still global...

I guess this should be something like

struct flag initFlag = { 0, 0, 0, {0}, 5.4, 0, 4.5 };

but I think C99 syntax is more clear...
#define VERIFY(...) { int table[] = { __VA_ARGS__, 1 };

printf("%d",table);
Huh? Here, there's a mismatch in the format specifier for
printf(); the variadic portion of the macro arguments can only
take on 'int' values; called with no arguments, the macro will
not even compile; the macro is not brace-balanced (missing one
closing } brace); and I have no idea what its point is.
But certainly it can't be compiled with a C89 compiler, either!


In fact the missing brace is a typo...

Thank you for your explanations ^^



Nov 13 '05 #97
In article <bq**********@news.tudelft.nl>, si****@jigsaw.nl says...
Paul Hsieh wrote:
Sidney Cadot <si****@jigsaw.nl> wrote:
[...] I for one would be happy if more compilers would
fully start to support C99, It will be a good day when I can actually
start to use many of the new features without having to worry about
portability too much, as is the current situation.
I don't think that day will ever come. In its totallity C99 is almost
completely worthless in real world environments. Vendors will be
smart to pick up restrict and few of the goodies in C99 and just stop
there.
Want to take a bet...?


Sure. Vendors are waiting to see what the C++ people do, because they are well
aware of the unreconcilable conflicts that have arisen. Bjarne and crew are
going to be forced to take the new stuff C99 in the bits and pieces that don't
cause any conflict or aren't otherwise stupid for other reasons. The Vendors
are going to look at this and decide that the subset of C99 that the C++ people
chose will be the least problematic solution and just go with that.
If instead, the preprocessor were a lot more functional, then you
could simply extract packed offsets from a list of declarations and
literally plug them in as offsets into a char[] and do the slow memcpy
operations yourself.


This would violate the division between preprocessor and compiler too
much (the preprocessor would have to understand quite a lot of C semantics).


No, that's not what I am proposing. I am saying that you should not use
structs at all, but you can use the contents of them as a list of comma
seperated entries. With a more beefed up preprocessor one could find the
offset of a packed char array that corresponds to the nth element of the list
as a sum of sizeof()'s and you'd be off to the races. So I am not proposing
that the preprocessor know anything more about the C language at all. I am
instead proposing that it be better at what it *does* know about -- numbers,
macros, and various C-language compatible tokens.
* a clear statement concerning the minimal level of active function
calls invocations that an implementation needs to support.
Currently, recursive programs will stackfault at a certain point,
and this situation is not handled satisfactorily in the standard
(it is not adressed at all, that is), as far as I can tell.
That doesn't seem possible. The amount of "stack" that an
implementation might use for a given function is clearly not easy to
define. Better to just leave this loose.


It's not easy to define, that's for sure. But to call into recollection
a post from six weeks ago: [...] ...This is legal C (as per the Standard),
but it overflows the stack on any implementation (which is usually a
sumptom of UB). Why is there no statement in the standard that even so much
as hints at this?


isgraph(-1) is also legal C -- *SYNTACTICALLY*. There is no end of problems
with the C programming environment. To gripe about runtime stack depth
limitations alone I think is kind of pointless. C is a language suitable for
and high encouraging of writing extremely unsound and poor code. Fixing it
would require a major overhaul of the language and library.
* a library function that allows the retrieval of the size of a memory
block previously allocated using "malloc"/"calloc"/"realloc" and
friends.


There's a lot more that you can do as well. Such as a tryexpand()
function which works like realloc except that it performs no action
except returning with some sort of error status if the block cannot be
resized without moving its base pointer. Further, one would like to
be able to manage *multiple* heaps, and have a freeall() function --
it would make the problem of memory leaks much more manageable for
many applications. It would almost make some cases enormously faster.


But this is perhaps territory that the Standard should steer clear of,
more like something a well-written and dedicated third-party library
could provide.


But a third party library can't do this portably. Its actual useful
functionality that you just can't get from the C language, and there's no way
to reliably map such functionality to the C language itself. One is forced to
know the details of the underlying platform to implement such things. Its
something that really *should* be in the language.
* a #define'd constant in stdio.h that gives the maximal number of
characters that a "%p" format specifier can emit. Likewise, for
other format specifiers such as "%d" and the like.

* a printf format specifier for printing numbers in base-2.
Ah -- the kludge request.


I'd rather see this as filling in a gaping hole.
Rather than adding format specifiers one at
a time, why not instead add in a way of being able to plug in
programmer-defined format specifiers?


Because that's difficult to get right (unlike a proposed binary output
form).


There are sources for snprintf available that can do it. You are asking for
this feature because you think it would be useful *FOR YOU*. I convert hex to
binary in my head without barely thinking and would rather use the screen space
for more pertinant things, so it would not be useful for me. My proposal
allows the programmer to decide what is or is not useful them.
> I think people in general would
like to use printf for printing out more than just the base types in a
collection of just a few formats defined at the whims of some 70s UNIX
hackers. Why not be able to print out your data structures, or
relevant parts of them as you see fit?


The %x format specifier mechanism is perhaps not a good way to do this,
if only because it would only allow something like 15 extra output formats.


I'm not sure what you are saying here. You all of a sudden don't like the hex
printing format? And why is having more, user definable print formats a bad
thing?
* I think I would like to see a real string-type as a first-class
citizen in C, implemented as a native type. But this would open
up too big a can of worms, I am afraid, and a good case can be
made that this violates the principles of C too much (being a
low-level language and all).


The problem is that real string handling requires memory handling.
The other primitive types in C are flat structures that are fixed
width. You either need something like C++'s constructor/destructor
semantics or automatic garbage collection otherwise you're going to
have some trouble with memory leaking.


A very simple reference-counting implementation would suffice. [...]


This would complexify the compiler to no end. Its also hard to account for a
reference that was arrived at via something like "memcpy".
* Normative statements on the upper-bound worst-case asymptotic
behavior of things like qsort() and bsearch() would be nice.


Yeah, it would be nice to catch up to where the C++ people have gone
some years ago.


I don't think it is a silly idea to have some consideration for
worst-case performance in the standard, especially for algorithmic
functions (of which qsort and bsearch are the most prominent examples).


Perhaps you misunderstand me. The fact the C committee *DIDN'T* do this is an
abomination. STL includes some kind of sorting mechanisms which are now
guaranteed to be O(n*log(n)) because of the existence of an algorithm called
"INTROSORT" (which is really just a quicksort that aborts when it realizes its
going too slow, and switches to heapsort -- but the authors think its clever
because they do this determiniation recursively.)
* a "reverse comma" type expression, for example denoted by
a reverse apastrophe, where the leftmost value is the value
of the entire expression, but the right-hand side is also
guaranteed to be executed.


This seems too esoteric.


Why is it any more esoteric than having a comma operator?


I didn't say was. I've never used the comma operator outside of an occasional
extra command at the end of the increment statement in a for loop in my life.
I consider comma to be esoteric as well.
* triple-&& and triple-|| operators: &&& and ||| with semantics
like the 'and' and 'or' operators in python:

a &&& b ---> if (a) then b else a
a ||| b ---> if (a) then a else b

(I think this is brilliant, and actually useful sometimes).


Hmmm ... why not instead have ordinary operator overloading?


I'll provide three reasons.

1) because it is something completely different


Yeah its a superset that has been embraced by the C++ community.
2) because it is quite unrelated (I don't get the 'instead')
I'm saying that you could have &&&, |||, but just don't defined what they
actually do. Require that the programmer define what they do. C doesn't have
type-specific functions, and if one were to add in operator overloading in a
consistent way, then that would mean that an operator overload would have to
accept only its defined type. For this to be useful without losing the
operators that already exist in C, the right answer is to *ADD* operators. In
fact I would suggest that one simply defined a grammar for such operators, and
allow *ALL* such operators to be definable.
3) because operator overloading is mostly a bad idea, IMHO
Well, Bjarne Stroustrup has made a recent impassioned request to *REMOVE*
features from C++. I highly doubt that operator overloading is one that has
been made or would be taken seriously. I.e., I don't think a credible
population of people who have been exposed to it would consider it a bad idea.
While
this is sometimes a useful shorthand, I am sure that different
applications have different list cutesy compactions that would be
worth while instead of the one above.


... I'd like to see them. &&& is a bit silly (it's fully equivalent to
"a ? b : 0") but ||| (or ?: in gcc) is actually quite useful.


But there are no end of little cheesy operators that one could add. For
example, a <> b to swap a and b, a <<< b to rotate a by b bits, @ a to find the
highest bit of a, etc., etc., etc. All of these are good, in some cases. And
I think that there would be no end to the number of useful operators that one
might like to add to a program. I think your proposal is DOA because you
cannot make a credible case as to why your operator in particular has any value
over any of number of other operators that you might like to add.

Adding operator overloading, however, would be a real extension and would in a
sense address *all* these issues.
* a way to "bitwise invert" a variable without actually
assigning, complementing "&=", "|=", and friends.


Is a ~= a really that much of a burden to type?


It's more a strain on the brain to me, why there are coupled
assignment/operators for neigh all binary operators, but not for this
unary one.


Ok, but then again this is just a particular thing with you.
* 'min' and 'max' operators (following gcc: ?< and ?>)


As I mentioned above, you might as well have operator overloading instead.


Now I would ask you: which existing operator would you like to overload
for, say, integers, to mean "min" and "max" ?


How about a <==> b for max and a >==< b for min? I personally don't care that
much.
* a div and matching mod operator that round to -infinity,
to complement the current less useful semantics of rounding
towards zero.
Well ... but this is the very least of the kinds of arithmetic operator
extensions that one would want. A widening multiply operation is
almost *imperative*. It always floors me that other languages are not
picking this up. Nearly every modern microprocessor in existence has
a widening multiply operation -- because the CPU manufacturer *KNOW*
its necessary. And yet its not accessible from any language.


...It already is available in C, given a good-enough compiler. Look at
the code gcc spits out when you do:

unsigned long a = rand();
unsigned long b = rand();

unsigned long long c = (unsigned long long)a * b;


Yes I'm sure the same trick works for chars and shorts. So how do you widen a
long long multiply?!?!? What compiler trick are you going to hope for to
capture this? What you show here is just some trivial *SMALL* multiply, that
relies on the whims of the optimizer.

PowerPC, Alpha, Itanium, UltraSPARC and AMD64 all have widening multiplies that
take two 64 bit operands and returns a 128 bit result in a pair of 64 bit
operands. They all invest a *LOT* of transistors to do this *ONE* operation.
They all *KNOW* you can't finagle any C/C++ compiler to produce the operation,
yet they still do it -- its *THAT* important (hint: SSL, and therefore *ALL* of
e-commerce, uses it.)
Probably because most languages have been written on top of C or C++.
And what about a simple carry capturing addition?


Many languages exists where this is possible, they are called
"assembly". There is no way that you could come up with a well-defined
semantics for this.


carry +< var = a + b;
Did you know that a PowerPC processor doesn't have a shift-right where
you can capture the carry bit in one instruction? Silly but no less true.


What has this got to do with anything? Capturing carries coming out of shifts
don't show up in any significant algorithms that I am aware of that are
significantly faster than using what we have already. The specific operations
I am citing make a *HUGE* difference and have billion dollar price tags
associated with them.

I understand the need for the C language standard to be applicable to as many
platforms as possible. But unlike some right shift detail that you are talking
about, the widening multiply hardware actually *IS* deployed everywhere.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
Nov 13 '05 #98
Paul Hsieh wrote:
In article <bq**********@news.tudelft.nl>, si****@jigsaw.nl says...
Paul Hsieh wrote:
Sidney Cadot <si****@jigsaw.nl> wrote:

[...] I for one would be happy if more compilers would
fully start to support C99, It will be a good day when I can actually
start to use many of the new features without having to worry about
portability too much, as is the current situation.
I don't think that day will ever come. In its totallity C99 is almost
completely worthless in real world environments. Vendors will be
smart to pick up restrict and few of the goodies in C99 and just stop
there.


Want to take a bet...?

Sure. Vendors are waiting to see what the C++ people do, because they are well
aware of the unreconcilable conflicts that have arisen. Bjarne and crew are
going to be forced to take the new stuff C99 in the bits and pieces that don't
cause any conflict or aren't otherwise stupid for other reasons. The Vendors
are going to look at this and decide that the subset of C99 that the C++ people
chose will be the least problematic solution and just go with that.


Ok. I'll give you 10:1 odds; there will be a (near-perfect) C99 compiler
by the end of this decade.
If instead, the preprocessor were a lot more functional, then you
could simply extract packed offsets from a list of declarations and
literally plug them in as offsets into a char[] and do the slow memcpy
operations yourself.


This would violate the division between preprocessor and compiler too
much (the preprocessor would have to understand quite a lot of C semantics).

No, that's not what I am proposing. I am saying that you should not use
structs at all, but you can use the contents of them as a list of comma
seperated entries. With a more beefed up preprocessor one could find the
offset of a packed char array that corresponds to the nth element of the list
as a sum of sizeof()'s and you'd be off to the races.


Perhaps I'm missing something here, but wouldn't it be easier to use the
offsetof() macro?
So I am not proposing
that the preprocessor know anything more about the C language at all. I am
instead proposing that it be better at what it *does* know about -- numbers,
macros, and various C-language compatible tokens.
Ok. It may make sense to extend the preprocessor.
It's not easy to define, that's for sure. But to call into recollection
a post from six weeks ago: [...] ...This is legal C (as per the Standard),
but it overflows the stack on any implementation (which is usually a
sumptom of UB). Why is there no statement in the standard that even so much
as hints at this? isgraph(-1) is also legal C -- *SYNTACTICALLY*. There is no end of problems
with the C programming environment. To gripe about runtime stack depth
limitations alone I think is kind of pointless.
Well, I showed a perfectly legal C program that should happily run and
terminate if I am to believe the standard, yet it doesn't do that on any
architecture. Excuse me for being a bit unhappy about that.
C is a language suitable for
and high encouraging of writing extremely unsound and poor code. Fixing it
would require a major overhaul of the language and library.
That's true. I don't quite see how this relates to the preceding
statement though.
There's a lot more that you can do as well. Such as a tryexpand()
function which works like realloc except that it performs no action
except returning with some sort of error status if the block cannot be
resized without moving its base pointer. Further, one would like to
be able to manage *multiple* heaps, and have a freeall() function --
it would make the problem of memory leaks much more manageable for
many applications. It would almost make some cases enormously faster.


But this is perhaps territory that the Standard should steer clear of,
more like something a well-written and dedicated third-party library
could provide. But a third party library can't do this portably.
I don't see why not?
Its actual useful
functionality that you just can't get from the C language, and there's no way
to reliably map such functionality to the C language itself. One is forced to
know the details of the underlying platform to implement such things. Its
something that really *should* be in the language.
Well, it looks to me you're proposing to have a feature-rich heap
manager. I honestly don't see you this couldn't be implemented portably
without platform-specific knowledge. Could you elaborate?
* a printf format specifier for printing numbers in base-2.

Ah -- the kludge request.


I'd rather see this as filling in a gaping hole.
Rather than adding format specifiers one at
a time, why not instead add in a way of being able to plug in
programmer-defined format specifiers?


Because that's difficult to get right (unlike a proposed binary output
form). There are sources for snprintf available that can do it. You are asking for
this feature because you think it would be useful *FOR YOU*.
Yes, and for a bunch of other people.
I convert hex to binary in my head without barely thinking and would rather
use the screen space for more pertinant things, so it would not be useful for me.

I can do it blindfolded, with my hands tied behind my back, at an
ambient noise level that makes most people lose bladder control. I
wouldn't use it all the time mind you, but it's just plain silly to be
able to do hex, octal, and decimal, but not binary. I want this more for
reasons of orthogonality in design than anything else.
My proposal allows the programmer to decide what is or is not useful them.
I'm all for that.
> I think people in general would
like to use printf for printing out more than just the base types in a
collection of just a few formats defined at the whims of some 70s UNIX
hackers. Why not be able to print out your data structures, or
relevant parts of them as you see fit?
I don't think it's too bad an idea (although I have never gotten round
to trying the mechanism gcc provides for this). In any case, this kind
of thing is so much more naturally done in a OOP-supporting language
like C++ . Without being bellingerent: why not use that if you want this
kind of thing?
The %x format specifier mechanism is perhaps not a good way to do this,
if only because it would only allow something like 15 extra output formats. I'm not sure what you are saying here. You all of a sudden don't like the hex
printing format? And why is having more, user definable print formats a bad
thing?
I used "%x" as an example of a format specifier that isn't defined ('x'
being a placeholder for any letter that hasn't been taken by the
standard). The statement is that there'd be only 15 about letters left
for this kind of thing (including 'x' by the way -- it's not a hex
specifier). Sorry for the confusion, I should've been clearer.
* I think I would like to see a real string-type as a first-class
citizen in C, implemented as a native type. But this would open
up too big a can of worms, I am afraid, and a good case can be
made that this violates the principles of C too much (being a
low-level language and all).

The problem is that real string handling requires memory handling.
The other primitive types in C are flat structures that are fixed
width. You either need something like C++'s constructor/destructor
semantics or automatic garbage collection otherwise you're going to
have some trouble with memory leaking.


A very simple reference-counting implementation would suffice. [...]


This would complexify the compiler to no end. Its also hard to account for a
reference that was arrived at via something like "memcpy".


A first-class citizen string wouldn't be a pointer; neither would you
necessarily be able to get its address (although you should be able to
get the address of the characters it contains).
* Normative statements on the upper-bound worst-case asymptotic
behavior of things like qsort() and bsearch() would be nice.

Yeah, it would be nice to catch up to where the C++ people have gone
some years ago.


I don't think it is a silly idea to have some consideration for
worst-case performance in the standard, especially for algorithmic
functions (of which qsort and bsearch are the most prominent examples).


Perhaps you misunderstand me. The fact the C committee *DIDN'T* do this is an
abomination. STL includes some kind of sorting mechanisms which are now
guaranteed to be O(n*log(n)) because of the existence of an algorithm called
"INTROSORT" (which is really just a quicksort that aborts when it realizes its
going too slow, and switches to heapsort -- but the authors think its clever
because they do this determiniation recursively.)


Sorry about that, I thought you were sarcastic. Ok, then we agree on
this. Moving on...
* a "reverse comma" type expresion, for example denoted by
a reverse apastrophe, where the leftmost value is the value
of the entire expression, but the right-hand side is also
guaranteed to be executed.

This seems too esoteric.


Why is it any more esoteric than having a comma operator?


I didn't say was. I've never used the comma operator outside of an occasional
extra command at the end of the increment statement in a for loop in my life.
I consider comma to be esoteric as well.


Ok, that's a valid opinion that I don't happen to share.
* triple-&& and triple-|| operators: &&& and ||| with semantics
like the 'and' and 'or' operators in python:

a &&& b ---> if (a) then b else a
a ||| b ---> if (a) then a else b

(I think this is brilliant, and actually useful sometimes).

Hmmm ... why not instead have ordinary operator overloading?


I'll provide three reasons.

1) because it is something completely different Yeah its a superset that has been embraced by the C++ community.
It's a superset only if the C language would have a ||| or &&& operator
in the first place. Which (much to my dismay) it doesn't.
2) because it is quite unrelated (I don't get the 'instead') I'm saying that you could have &&&, |||, but just don't defined what they
actually do. Require that the programmer define what they do. C doesn't have
type-specific functions, and if one were to add in operator overloading in a
consistent way, then that would mean that an operator overload would have to
accept only its defined type.
Ok, so the language should have a big bunch of operators, ready for the
taking. Incidentally, Mathematica supports this, if you want it badly.
For this to be useful without losing the
operators that already exist in C, the right answer is to *ADD* operators. In
fact I would suggest that one simply defined a grammar for such operators, and
allow *ALL* such operators to be definable.
This seems to me a bad idea for a multitude of reasons. First, it would
complicate most stages of the compiler considerably. Second, a
maintenance nightmare ensues: while the standard operators of C are
basically burnt into my soul, I'd have to get used to the Fantasy
Operator Of The Month every time I take on a new project, originally
programmed by someone else.

There's a good reason that we use things like '+' and '*' pervasively,
in many situations; they are short, and easily absorbed in many
contexts. Self-defined operator tokens (consisting, of course, of
'atomic' operators like '+', '=', '<' ...) will lead to unreadable code,
I think; perhaps something akin to a complicated 'sed' script.
3) because operator overloading is mostly a bad idea, IMHO Well, Bjarne Stroustrup has made a recent impassioned request to *REMOVE*
features from C++.
Do you have a reference? That's bound to be a fun read, and he probably
missed a few candidates.
I highly doubt that operator overloading is one that has
been made or would be taken seriously. I.e., I don't think a credible
population of people who have been exposed to it would consider it a bad idea.
I can only speak for myself; I have been exposed, and think it's a bad
idea. When used very sparsely, it has it's uses. However, introducing
new user-definable operators as you propose would be folly; the only way
operator overloading works in practice is if you maintain some sort of
link to the intuitive meaning of an operator. User defined operators
lack this by definition.
While
this is sometimes a useful shorthand, I am sure that different
applications have different list cutesy compactions that would be
worth while instead of the one above.


... I'd like to see them. &&& is a bit silly (it's fully equivalent to
"a ? b : 0") but ||| (or ?: in gcc) is actually quite useful. But there are no end of little cheesy operators that one could add. For
example, a <> b to swap a and b, a <<< b to rotate a by b bits, @ a to find the
highest bit of a, etc., etc., etc.
"<>" would be a bad choice, since it is easy to confuse for "not equal
to". I've programmed a bit in IDL for a while, which has my dear "min"
and "max" operators.... It's a pity they are denoted "<" and ">",
leading to heaps of misery by confusion.

<<< and @ are nice though. I would be almost in favour of adding them,
were it not for the fact that this would drive C dangerously close in
the direction of APL.
All of these are good, in some cases. And
I think that there would be no end to the number of useful operators that one
might like to add to a program. I think your proposal is DOA because you
cannot make a credible case as to why your operator in particular has any value
over any of number of other operators that you might like to add.
Adding operator overloading, however, would be a real extension and would in a
sense address *all* these issues.
Again I wonder, seriously: wouldn't you be better of using C++ ?
It's more a strain on the brain to me, why there are coupled
assignment/operators for neigh all binary operators, but not for this
unary one. Ok, but then again this is just a particular thing with you.
Guilty as charged.
* 'min' and 'max' operators (following gcc: ?< and ?>)

As I mentioned above, you might as well have operator overloading instead.
Sure, but you're talking about something that goes a lot further than
run-off-the-mill operator overloading. I think the simple way would be
to just introduce these min and max operators and be done with it.

"min" and "max" are perhaps less important than "+" and "*", but they
are probably the most-used operations that are not available right now
as operators. If we are going to extend C with new operators, they would
be the most natural choice I think.
Now I would ask you: which existing operator would you like to overload
for, say, integers, to mean "min" and "max" ? How about a <==> b for max and a >==< b for min? I personally don't care that
much.
Those are not existing operators, as you know. They would have to be
defined in your curious "operator definition" scheme.

I find the idea freaky, yet interesting. I think C is not the place for
this (really, it would be too easy to compete in the IOCCC) but perhaps
in another language... Just to follow your argument for a bit, what
would an "operator definition" declaration look like for, say, the "?<"
min operator in your hypothetical extended C?
Yes I'm sure the same trick works for chars and shorts. So how do you widen a
long long multiply?!?!? What compiler trick are you going to hope for to
capture this? What you show here is just some trivial *SMALL* multiply, that
relies on the whims of the optimizer.
Well, I'd show you, but it's impossible _in principle_. Given that you
are multiplying two expressions of the widest type supported by your
compiler, where would it store the result?
PowerPC, Alpha, Itanium, UltraSPARC and AMD64 all have widening multiplies that
take two 64 bit operands and returns a 128 bit result in a pair of 64 bit
operands. They all invest a *LOT* of transistors to do this *ONE* operation.
They all *KNOW* you can't finagle any C/C++ compiler to produce the operation,
yet they still do it -- its *THAT* important (hint: SSL, and therefore *ALL* of
e-commerce, uses it.)
Well, I don't know if these dozen-or-so big-number 'powermod' operations
that are needed to establish an SSL connection are such a big deal as
you make it.
Probably because most languages have been written on top of C or C++.
And what about a simple carry capturing addition?


Many languages exists where this is possible, they are called
"assembly". There is no way that you could come up with a well-defined
semantics for this.

carry +< var = a + b;
It looks cute, I'll give you that. Could you please provide semantics?
It may be a lot less self evident than you think.
Did you know that a PowerPC processor doesn't have a shift-right where
you can capture the carry bit in one instruction? Silly but no less true.

What has this got to do with anything? Capturing carries coming out of shifts
don't show up in any significant algorithms that I am aware of
that are significantly faster than using what we have already.
Ah, I see you've never implemented a non-table-driven CRC or a binary
greatest common divisor algorithm. They are both hard at work when you
establish an SSL connection.
The specific operations I am citing make a *HUGE* difference and have billion
dollar price tags associated with them.
These numbers you made up from thin air, no? otherwise, I'd welcome a
reference.
I understand the need for the C language standard to be applicable to as many
platforms as possible. But unlike some right shift detail that you are talking
about, the widening multiply hardware actually *IS* deployed everywhere.


Sure is. Several good big-number libraries are available that have
processor-dependent machine code to do just this.

Best regards,

Sidney

Nov 13 '05 #99
"Lorenzo Villari" <vl****@tiscali.it> wrote:
struct
{
char *expr;
int value;
} lexer ['z' - 'a'] = { ['b' - 'a'] = { "[a-zA-Z]", 0 }, ... };


This is unportable. The only characters that can be reliably
subtracted in C are the digits. '0' through '9' are guaranteed
to be consecutive. Letters need not be consecutive, and need
not even be in alphabetical order.

--
Simon.
Nov 13 '05 #100

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Anthony Martin | last post by:
I've been reading the Java Language Specification, and in Chapter 16 there's an interesting topic called Definite Assignment. http://tinyurl.com/3fqk8 I'm wondering about the idea of "Deferred...
14
by: Medi Montaseri | last post by:
Hi, I think my problem is indeed "how to implement something like java's final in C++" The long version.... I have an abstract base class which is inherited by several concrete classes. I...
48
by: David J Patrick | last post by:
I'm trying to rewrite the CSS used in http://s92415866.onlinehome.us/files/ScreenplayCSSv2.html. using the w3.org paged media standards as described at http://www.w3.org/TR/REC-CSS2/page.html ...
10
by: Bezalel Bareli | last post by:
I know I have seen some threads on the subject long time ago and it was using a virtual base class ... in short, what is the nicest way to implement the Java final class in c++ Thanks.
14
by: My4thPersonality | last post by:
Has the fact that both Java and C# are garbage collected, and C++ in not, anything to do with the fact that there is no language item to prevent a class from being inherired from? I once read that...
1
by: silverburgh.meryl | last post by:
I am trying to convert this code from java to c++: public final class Type { public static final int DEFAULT = 1; private static int index = 2; public static final int COLUMN1 = (int)...
5
by: Anthony Baxter | last post by:
On behalf of the Python development team and the Python community, I'm happy to announce the release of Python 2.4.3 (final). Python 2.4.3 is a bug-fix release. See the release notes at the...
14
by: Rahul | last post by:
Hi Everyone, I was searching for final class in c++, and i came across few links which suggests to have the constructor of the, to be final class, as private so that any derived class's...
1
by: Rajib | last post by:
Not that this serves any real purpose, but gcc allows me to do some hack like this: class hide_A { public: class A { public: virtual int final() { return 42; } };
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.