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

Wirth-ian languages

85 views
Skip to first unread message

bruce axtens

unread,
Apr 28, 2014, 12:23:05 PM4/28/14
to
Is it fair to say that most of the Wirth-ian programming languages are
either dead or in palliative care? Delphi seems to be about the only
thing left with any life in it. Am I missing anything?

-- Bruce

Joe Hynes

unread,
Apr 28, 2014, 1:31:47 PM4/28/14
to
There's a pretty active FreePascal project and there's always Ada.
There's enough legacy Ada to keep quite a few people in business and there
always seems to be some small amount of new Ada going on. Personally, I
believe Ada is Wirthian in spirit but there were and are some damn good
language designers and implementers involved with it. Ada is mostly a clean
sheet of paper even though it may not look like that. I mean Ada up to
around 95. After that things started to deteriorate into the C++ world of
complexity and lack of restraint. Now it's harder to see its roots.

Modula-3 has a small but active community also.

What do you want to conclude? Probably Wirth's priorities and aesthetics are
not widely shared by people who choose programming languages for deployment.
gcc and Linux have taken over and blotted out most of the native species.
Linux is based on C so using anything but C/C++ will eventually bring
you to a wall you can't scale. Most people don't get there but the constant
stomping out of anything that isn't gcc has been very destructive and
limiting generally.

That and in the old days most of the technical stuff was left to technical
people. Ever since the Harvard MBA program the CEO and people that have no
idea what they're talking about are the ones choosing stuff that most code
is written in. Their choices are not usually based on technical or
engineering criteria.

Then there's the ivory tower of academia where most of what they teach is
useless or harmful and wrong. But it sticks. They go with the lowest common
denominator and that eventually slimes over to industry where the unwashed
masses that used Java and C++ in college spec it for whatever comes up. Java
was marketed real hard and well and so was C++.

Wirth was unusual in that his sense of elegance was not impractical and
didn't fall into Dijkstra's hubris sinkhole and become a public display of
circle-jerkery. Wirth came up with basic good ideas and elegant solutions
that that other people were able to use to create truly useful things
from. Aside from Wirth and Stroustrup it's been extremely rare to see
anything come out of academia but hot air. And that's on a good day.

Joe

Kaz Kylheku

unread,
Apr 28, 2014, 2:47:23 PM4/28/14
to
On 2014-04-28, Joe Hynes <th...@southpark.net> wrote:
> On 2014-04-28, bruce axtens <bugm...@outlook.com> wrote:
>> Is it fair to say that most of the Wirth-ian programming languages are
>> either dead or in palliative care? Delphi seems to be about the only
>> thing left with any life in it. Am I missing anything?
>
> There's a pretty active FreePascal project and there's always Ada.
> There's enough legacy Ada to keep quite a few people in business and there
> always seems to be some small amount of new Ada going on. Personally, I
> believe Ada is Wirthian in spirit but there were and are some damn good
> language designers and implementers involved with it. Ada is mostly a clean
> sheet of paper even though it may not look like that. I mean Ada up to
> around 95. After that things started to deteriorate into the C++ world of
> complexity and lack of restraint. Now it's harder to see its roots.
>
> Modula-3 has a small but active community also.
>
> What do you want to conclude? Probably Wirth's priorities and aesthetics are
> not widely shared by people who choose programming languages for deployment.
> gcc and Linux have taken over and blotted out most of the native species.
> Linux is based on C so using anything but C/C++ will eventually bring
> you to a wall you can't scale.

C is pretty much a "Wirthian" language. The basic model of program organization
and comptuation in, say, Modula-2 or C is the same: statically typed, block
scoped language based on machine-language-like primitive types, and simple
aggregates thereof, with poor support for polymorphism. Programs in these
languages define "mills" that pump word-sized data through a Von Neumann
machine.

Nobody really needs alternatives to C which are almost the same thing,
just with more clunky syntax and pointless limitations.

> Most people don't get there but the constant
> stomping out of anything that isn't gcc has been very destructive and
> limiting generally.

Nobody is holding gun to anyone's head regarding what to include in a distro
of free software, and you can start your own if you don't like any of them.

Freeware distros give you more programming languages as standard packages
than any proprietary OS.

> That and in the old days most of the technical stuff was left to technical
> people. Ever since the Harvard MBA program the CEO and people that have no
> idea what they're talking about are the ones choosing stuff that most code
> is written in.

Even if that is true now, it has no bearing on the rejection of things
Pascalian, which is rooted in the old days.

When Lisp hacker Richard Stallman decided, the middle 1980's that the thing
to do to kickstart the freware movement was to make a C compiler, that probably
didn't have to do with Havard MBA's choosing stuff that code is written in.

Look, even Knuth caved in: http://www-cs-faculty.stanford.edu/~uno/faq.html
See: "What is your favorite programming language". That was more than 20 years
ago.

BartC

unread,
Apr 28, 2014, 3:35:13 PM4/28/14
to
"Kaz Kylheku" <k...@kylheku.com> wrote in message
news:201404281...@kylheku.com...
> On 2014-04-28, Joe Hynes <th...@southpark.net> wrote:
>> On 2014-04-28, bruce axtens <bugm...@outlook.com> wrote:
>>> Is it fair to say that most of the Wirth-ian programming languages are
>>> either dead or in palliative care? Delphi seems to be about the only
>>> thing left with any life in it. Am I missing anything?

>> What do you want to conclude? Probably Wirth's priorities and aesthetics
>> are
>> not widely shared by people who choose programming languages for
>> deployment.
>> gcc and Linux have taken over and blotted out most of the native species.
>> Linux is based on C so using anything but C/C++ will eventually bring
>> you to a wall you can't scale.
>
> C is pretty much a "Wirthian" language. The basic model of program
> organization
> and comptuation in, say, Modula-2 or C is the same: statically typed,
> block
> scoped language based on machine-language-like primitive types, and simple
> aggregates thereof, with poor support for polymorphism. Programs in these
> languages define "mills" that pump word-sized data through a Von Neumann
> machine.
>
> Nobody really needs alternatives to C which are almost the same thing,
> just with more clunky syntax and pointless limitations.

Yes we do. It wouldn't take me long to list a hundred things that are wrong
with C, yet after fixing all those the resulting language wouldn't do that
much more. It would just get rid of all the baggage, and have a smaller,
tidier and more streamlined language that is far nicer to use.

>> Most people don't get there but the constant
>> stomping out of anything that isn't gcc has been very destructive and
>> limiting generally.
>
> Nobody is holding gun to anyone's head regarding what to include in a
> distro
> of free software, and you can start your own if you don't like any of
> them.
>
> Freeware distros give you more programming languages as standard packages
> than any proprietary OS.

> Look, even Knuth caved in:
> http://www-cs-faculty.stanford.edu/~uno/faq.html
> See: "What is your favorite programming language". That was more than 20
> years
> ago.

Is this the same guy who devised MIX, a made-up machine language, to
describe algorithms in his books? He probably isn't too hot on designing
elegant languages then. And he may have been partly forced to migrate to C
for the same reasons everyone else has found it necessary to move in that
direction.

I even started to move there myself a year and a half ago, but am now
rebelling and moving away again to do my own thing.

There are a couple of things that are good about C: the language is
ubiquitous, and compilers for it can generate pretty good code. But that
says nothing about the language itself, which 'sucks' (and even C
programmers agree about some of its problems).

But there is little else that can do the same job (ie. implement everything
else from the ground up). Hence the need for an alternative.

--
Bartc

Kaz Kylheku

unread,
Apr 28, 2014, 4:18:20 PM4/28/14
to
On 2014-04-28, BartC <b...@freeuk.com> wrote:
> "Kaz Kylheku" <k...@kylheku.com> wrote in message
>> Nobody really needs alternatives to C which are almost the same thing,
>> just with more clunky syntax and pointless limitations.
>
> Yes we do. It wouldn't take me long to list a hundred things that are wrong
> with C, yet after fixing all those the resulting language wouldn't do that

You'd have to read the specification of C first, or else few would
take you seriously. That could burn up a chunk of time.

> much more. It would just get rid of all the baggage, and have a smaller,
> tidier and more streamlined language that is far nicer to use.

C is already small enough to the point of being stupidly small.

>>> Most people don't get there but the constant
>>> stomping out of anything that isn't gcc has been very destructive and
>>> limiting generally.
>>
>> Nobody is holding gun to anyone's head regarding what to include in a
>> distro
>> of free software, and you can start your own if you don't like any of
>> them.
>>
>> Freeware distros give you more programming languages as standard packages
>> than any proprietary OS.
>
>> Look, even Knuth caved in:
>> http://www-cs-faculty.stanford.edu/~uno/faq.html
>> See: "What is your favorite programming language". That was more than 20
>> years
>> ago.
>
> Is this the same guy who devised MIX, a made-up machine language, to
> describe algorithms in his books? He probably isn't too hot on designing

It's also the same guy who wrote TeX in Pascal, using a "literate programming"
tool of his own design, so that the program and its documentation could be
produced from the same sources.

In a 1993 interview with "Computer Literacy Bookshops"
(http://tex.loria.fr/litte/knuth-interview) Knuth said:

CLB: Did you integrate WEB with C because so many programmers today are using
it, or do you personally like C and write with it?

Knuth: I think C has a lot of features that are very important. The
way C handles pointers, for example, was a brilliant innovation; it
solved a lot of problems that we had before in data structuring and
made the programs look good afterwards. C isn't the perfect language,
no language is, but I think it has a lot of virtues, and you can avoid
the parts you don't like. I do like C as a language, especially
because it blends in with the operating system (if you're using UNIX,
for example).

All through my life, I've always used the programming language that
blended best with the debugging system and operating system that I'm
using. If I had a better debugger for language X, and if X went well
with the operating system, I would be using that.

[Then he goes on to discuss an extreme case of X, where X was
some awful language called IMP on some early Cray machine, but he used it
anyway because it was well supported.]

It's clear that Knuth switched to C partly due to impetus, but he also likes
many of its spects, like how pointers are represented.

> There are a couple of things that are good about C: the language is
> ubiquitous, and compilers for it can generate pretty good code. But that
> says nothing about the language itself, which 'sucks' (and even C
> programmers agree about some of its problems).

Yes.

C has too many undefined behaviors, and also insufficient "reflection".

C could benefit from standardized access under the hood to answer questions
like "what function called me?" "what is the backtrace?" "how many arguments
were passed to me?" (or how many arguments are in this va_list?)

(Even if some of these things can't be implemented in some systems, it's better
if there is a standard API on those systems where it can be, and way to test
whether it is available.)

C would be a much better language if the operands of all operators, and
function arguments, evaluated strictly from left to right, and the whole
"sequence point" concept were discarded.

A longjmp which doesn't trash local variables would be nice, as well to have a
way to execute clean-up code unconditionally when a block is terminated by any
means.

James Harris

unread,
Apr 28, 2014, 5:50:34 PM4/28/14
to
"Kaz Kylheku" <k...@kylheku.com> wrote in message
news:201404281...@kylheku.com...
> On 2014-04-28, BartC <b...@freeuk.com> wrote:
>> "Kaz Kylheku" <k...@kylheku.com> wrote in message

...

> Knuth: I think C has a lot of features that are very important. The
> way C handles pointers, for example, was a brilliant innovation; it
> solved a lot of problems that we had before in data structuring and
> made the programs look good afterwards. C isn't the perfect language,
> no language is, but I think it has a lot of virtues, and you can avoid
> the parts you don't like. I do like C as a language, especially
> because it blends in with the operating system (if you're using UNIX,
> for example).

That's an interesting association between language and OS. As I am working
on both I have often seen a lot of overlap and tried hard to keep the two
concepts separate but together they do form a sort of programming system or
algorithm execution environment. There does seem to be a synergy between the
two concepts that can benefit a software developer.

> All through my life, I've always used the programming language that
> blended best with the debugging system and operating system that I'm
> using. If I had a better debugger for language X, and if X went well
> with the operating system, I would be using that.
>
> [Then he goes on to discuss an extreme case of X, where X was
> some awful language called IMP on some early Cray machine, but he used it
> anyway because it was well supported.]
>
> It's clear that Knuth switched to C partly due to impetus, but he also
> likes
> many of its spects, like how pointers are represented.
>
>> There are a couple of things that are good about C: the language is
>> ubiquitous, and compilers for it can generate pretty good code. But that
>> says nothing about the language itself, which 'sucks' (and even C
>> programmers agree about some of its problems).
>
> Yes.
>
> C has too many undefined behaviors, and also insufficient "reflection".
>
> C could benefit from standardized access under the hood to answer
> questions
> like "what function called me?" "what is the backtrace?" "how many
> arguments
> were passed to me?" (or how many arguments are in this va_list?)

Many things could be added to a function interface in C by adding extra
parameters. Calls don't have to be as minimal as they are; things could be
added but programmers would have to write the extra arguments individually.
Maybe they wouldn't like having to do that. Another language could provide
boxed tuples or store related data in lots of small pieces of memory.

> (Even if some of these things can't be implemented in some systems, it's
> better
> if there is a standard API on those systems where it can be, and way to
> test
> whether it is available.)
>
> C would be a much better language if the operands of all operators, and
> function arguments, evaluated strictly from left to right, and the whole
> "sequence point" concept were discarded.
>
> A longjmp which doesn't trash local variables would be nice, as well to
> have a
> way to execute clean-up code unconditionally when a block is terminated by
> any
> means.

That's interesting. I think we could all come up with a list of improvements
we would like.

I often think it strange that many people, including me, have so many issues
with C and yet it despite the things I don't like or wish could be better it
is still far and a away my language of choice for a lot of work. How can one
language be so bad yet so choosable? What makes it so good to program in
despite the faults that people identify? People, especially those who don't
use it, might be able to list a series of failings in its design and those
criticisms may be valid yet despite its faults it is still so effective and,
of course, very influential and good to use.

There are times I use Python or assembly depending on need but for a lot of
work C is in the Goldilocks position of being just right.

I see the comment above that Knuth switched to C which, for a theoretician,
is very interesting given the academic criticisms of the language.

In my own designs I tend to avoid including the features of C due to things
like their lack of security but then it becomes very difficult to provide
the same facilities in a secure way. I don't believe it is impossible but it
is challenging. C's semantics and associated features are mature and
complete enough to allow almost any job to be done well.

Rather than design a new language I wonder how feasible it would be for one
of us to evolve C into something better by means of a series of small steps.
The language base is there just asking to be improved. Anyone tried that?

To be clear I do not mean to add things to C so that it gradually accretes
more baggage. ISTM that other languages have done that and while they have
added some beneficial features they have become bulky and cumbersome as a
result. C++ I'm talking about you! I don't know why but while I have tried
to learn C++ a few times each time I feel myself losing the will to live. I
can see the sense in some of its changes, for sure, but something about the
language leaves me wanting to just go and do something more interesting. I
don't think I have ever felt that about C.

James


BartC

unread,
Apr 28, 2014, 7:03:20 PM4/28/14
to
"James Harris" <james.h...@gmail.com> wrote in message
news:ljmifb$1gn$1...@dont-email.me...
> "Kaz Kylheku" <k...@kylheku.com> wrote in message
<snip>
>> better
>> if there is a standard API on those systems where it can be, and way to
>> test
>> whether it is available.)
>>
>> C would be a much better language if the operands of all operators, and
>> function arguments, evaluated strictly from left to right, and the whole
>> "sequence point" concept were discarded.
>>
>> A longjmp which doesn't trash local variables would be nice, as well to
>> have a
>> way to execute clean-up code unconditionally when a block is terminated
>> by any
>> means.
>
> That's interesting. I think we could all come up with a list of
> improvements we would like.

I'll try and put something together. I may or may not post it. As I think
you say somewhere, such a list will be different for everyone.

> I often think it strange that many people, including me, have so many
> issues with C and yet it despite the things I don't like or wish could be
> better it is still far and a away my language of choice for a lot of work.
> How can one language be so bad yet so choosable? What makes it so good to
> program in despite the faults that people identify? People, especially
> those who don't use it, might be able to list a series of failings in its
> design and those criticisms may be valid yet despite its faults it is
> still so effective and, of course, very influential and good to use.

My own languages had plenty of problems of their own, but would always be my
first choice. (For one thing, I would spend considerably less time battling
the language and/or compiler, and more time on getting my work done.)

> There are times I use Python or assembly depending on need but for a lot
> of work C is in the Goldilocks position of being just right.

Yes, there is a need for such a language at this level. It's a shame it had
to be C. (And my own enhancements to it wouldn't make it much higher level;
I don't want to turn it into C++.)

> I see the comment above that Knuth switched to C which, for a
> theoretician, is very interesting given the academic criticisms of the
> language.
>
> In my own designs I tend to avoid including the features of C due to
> things like their lack of security but then it becomes very difficult to
> provide the same facilities in a secure way. I don't believe it is
> impossible but it is challenging. C's semantics and associated features
> are mature and complete enough to allow almost any job to be done well.

Try this one (an actual requirement I had): you have a pointer to a function
(in a dynamic library for example), and it needs N parameters (to keep
things simple, they're all of int type). How to call such a function in C
without writing N different calls? (Let's say N could be 0 to 12; so 13 lots
of calls.)

(In my languages, I would either step into inline assembly for this, or use
an odd statement I had called 'stack' which would push any expression onto
the hardware stack.)

> Rather than design a new language I wonder how feasible it would be for
> one of us to evolve C into something better by means of a series of small
> steps. The language base is there just asking to be improved. Anyone tried
> that?

I don't think it's possible without keeping all the bad stuff. It would be
easier to create a new language, and a few have come out (sadly inheriting
C's syntax in most cases). Not quite low level enough though.

For example, how do you get rid of the ghastly type declaration syntax in
one step?

> To be clear I do not mean to add things to C so that it gradually accretes
> more baggage. ISTM that other languages have done that and while they have
> added some beneficial features they have become bulky and cumbersome as a
> result. C++ I'm talking about you! I don't know why but while I have tried
> to learn C++ a few times each time I feel myself losing the will to live.

I've felt exactly the same. Usually when reading about the OO stuff. But my
own requirement is a little unusual as I only need a static compiled
language to code my interpreters in, and perhaps the odd library function.
It doesn't need to be big or have lots of advanced features.

--
Bartc

Kaz Kylheku

unread,
Apr 28, 2014, 7:51:53 PM4/28/14
to
On 2014-04-28, BartC <b...@freeuk.com> wrote:
> Try this one (an actual requirement I had): you have a pointer to a function
> (in a dynamic library for example), and it needs N parameters (to keep
> things simple, they're all of int type). How to call such a function in C
> without writing N different calls? (Let's say N could be 0 to 12; so 13 lots
> of calls.)

This capability is actually the subject of a library, which is part of a
collection of four libraries. Unfortunately, this collection, "libffcall", is
GNU licensed:

http://www.gnu.org/software/libffcall/

Though the libraries are GPL'ed, they provide a plausible API for doing
some very useful things which could be added to the C language. Or at least
cloned in the form of more permissive implementations.

Rod Pemberton

unread,
Apr 28, 2014, 8:59:12 PM4/28/14
to
On Mon, 28 Apr 2014 12:23:05 -0400, bruce axtens <bugm...@outlook.com>
wrote:

> Is it fair to say that most of the Wirth-ian programming languages are
> either dead or in palliative care? Delphi seems to be about the only
> thing left with any life in it. Am I missing anything?
>

I think it's dead. Most people on other newsgroups seem to argue
against me though when I say language 'X' or 'Y' or 'Z' is dead.
Other than BASIC, I think the languages of our era (being presumptuous
here) learned are dead: COBOL, FORTAN, Pascal, LISP, PL/I, Forth,
Ada, etc. BASIC still seems to have a life in limited situations,
e.g, industrial machines, hobbyists.

Whenever I point out that nearly all the newer languages use or have
used C as an intermediate representation, or as assembly, or derived
their internal code from compiled C code, I get attacked on that one
too, even though it's true. I can cite many of them.

C and C++ and various derivatives, like Java, "won" the language wars.
The other languages you see are all modern creations to handle various
modern issues: internet, websites, etc. IMO, the TIOBE index confirms
this. C and derivatives are the majority. Most others are insignificant.

As a high-level language, I liked Pascal for the most part. It had
some wierd stuff in it too though. It was well structured. The problem
with Pascal, almost three decades ago when I learned it, was it had two
serious problems. The first was that it didn't have pointers. This
was safe, but really complicated programming certain solutions. Others
have pointed out (pun-intended) that Pascal has pointers today. The
second was that there was no ability to access low-level features of
the machine. This was a problem in the era of cheap, personal, home
computers. You were trapped inside a box which couldn't control the
computer using Pascal. That's fine for some applications, but mostly
just prevented programmers from using their machines. Even BASIC of
that era provided mechanisms to do that, although they were custom to
each version of BASIC.


Rod Pemberton

Rod Pemberton

unread,
Apr 28, 2014, 9:10:51 PM4/28/14
to
On Mon, 28 Apr 2014 20:59:12 -0400, Rod Pemberton
<dont_us...@xnothavet.cqm> wrote:

> I think it's dead. Most people on other newsgroups seem to argue
> against me though when I say language 'X' or 'Y' or 'Z' is dead.
> Other than BASIC, I think the languages of our era (being presumptuous
> here) learned are dead: COBOL, FORTAN, Pascal, LISP, PL/I, Forth,

Delete "learned", editing error.

RP

Rod Pemberton

unread,
Apr 28, 2014, 9:46:00 PM4/28/14
to
On Mon, 28 Apr 2014 17:50:34 -0400, James Harris
<james.h...@gmail.com> wrote:

> I often think it strange that many people, including me, have so many
> issues with C and yet it despite the things I don't like or wish could be
> better it is still far and a away my language of choice for a lot of
> work.
> How can one language be so bad yet so choosable?

It's your perception of what is "bad" combined with your perception
of what is "useful." If you perceived other languages to be as
useful as C, then you wouldn't chose C, would you? I.e., decades
ago, when people had a choice of BASIC, Cobol, FORTRAN, or Pascal,
they usually chose BASIC. It was/is a general purpose language
good with integers and strings, albeit an unstructured language.

Although many argue for domain specific languages to solve specific
sets of problems, or argue for a high level of abstraction so that
mathematicians, physicists, or engineers can solve problems without
needing to learn how to reduce the problem to the machine level,
such languages don't work well when needed to make the machine do
something. The correct path, IMO, is for mathematicians, physicists,
and engineers to learn how to program real world machines, and learn
how to convert their problems into programs those machines can run.
Yes, I know that's not a popular perspective.

> What makes it so good to program in despite the faults that
> people identify?

I think it has two aspects. First, what C gets correct. Second,
when and where C gets stuff incorrect. Most of the incorrect
stuff is either trivial, low-use, or on the periphery.

I can identify quite a few and if you've seen my past posts, here,
a.o.d., a.l.a., c.l.a.x., you're probably aware of some of the many
faults of C.

So, let's list some (what I recall right now...) of what I think
C gets correct:

1) pointers
2) declaration syntax of objects matches usage syntax
3) symbols for symbolic operations not text, i.e., '<' instead of '.LT.'
4) curly braces for blocks
5) user doesn't have to manually maintain variables on a stack, or
manually setup and pass parameters to procedures
6) all objects map onto arrays of bytes
(ease of copying or moving blocks of data or loading files etc)
7) very good with strings and integers
8) fits the computing architecture of microprocessor based machines
9) supports two's complement arithmetic
10) nul terminated strings

It can be argued that many of these features, and others, exist in C
because the original authors (Kernighan, Ritchie, Thompson) ported
C to so many different computing platforms and had to redesign the
language to fit, as many as possible, as cleanly as possible.

Yes, I know some/many on that list are controversial too. Just mention
nul terminated strings in comp.lang.forth. Forth uses counted strings.
But, nul terminated strings solved the problem with incorrect lengths
on counted strings. Of course, it's possible in C to end up with
an unterminated string.

> In my own designs I tend to avoid including the features of C due to
> things like their lack of security but then it becomes very difficult
> to provide the same facilities in a secure way.

Bingo!

Lack of pointers is a serious problem to have. The Pascal that I learned
decades ago didn't have them. It was very difficult to solve some
basic problems without them. I'm not sure how Java etc get around the
issue. Of course, we've since learned that pointers can be very unsafe.
So, we have a power or flexibility versus safety issue.

> Rather than design a new language I wonder how feasible it would be for
> one of us to evolve C into something better by means of a series of small
> steps. The language base is there just asking to be improved. Anyone
> tried that?

I made a list of changes to C that could be done to C to create a safer,
better version of C. Each of these changes were compatible with the
C preprocessor. C's preprocessor can turn just about anything back into
valid C. E.g., I've disliked C's use of '=' for assignment. It should
be two characters to allow for searching without matching other assignment
operators in C. A simple define of ':=' to '=' will allow one to use
':=' for assignment. However, I moved on and starting developing my
own language, which I really dislike the syntax, but it parses easily.

> [C++]

Yes, many, including me see C++ as horrid. It does have a few nice ideas,
but the bulk of it ... seems to just layer on complexity for no reason.


Rod Pemberton

James Harris

unread,
Apr 29, 2014, 2:59:55 AM4/29/14
to
"BartC" <b...@freeuk.com> wrote in message
news:57B7v.161805$Qm2.1...@fx16.am4...

...

> Try this one (an actual requirement I had): you have a pointer to a
> function
> (in a dynamic library for example), and it needs N parameters (to keep
> things simple, they're all of int type). How to call such a function in C
> without writing N different calls? (Let's say N could be 0 to 12; so 13
> lots
> of calls.)

Perhaps I don't understand the requirement properly but wondered if you
could use the va_arg facilities. They may be unsafe but they are flexible.
If fp was the function pointer (and assuming that function pointers are
automartically derefrenced so the preceding * is not needed) could you do

fp(1, parm1);
fp(5, parm1, parm2, parm3, parm4, parm5);

etc?

> (In my languages, I would either step into inline assembly for this, or
> use
> an odd statement I had called 'stack' which would push any expression onto
> the hardware stack.)

Parms can also be stored as a block in memory. AIUI some would call this a
control block. The address of the control block can be passed to a function
such as

fp(&cb);

Would either that or the va_arg idea above solve the problem you mentioned?

>> Rather than design a new language I wonder how feasible it would be for
>> one of us to evolve C into something better by means of a series of small
>> steps. The language base is there just asking to be improved. Anyone
>> tried
>> that?
>
> I don't think it's possible without keeping all the bad stuff. It would be
> easier to create a new language, and a few have come out (sadly inheriting
> C's syntax in most cases). Not quite low level enough though.
>
> For example, how do you get rid of the ghastly type declaration syntax in
> one step?

Could you not declare variables and constants in your own preferred way? You
mean it's hard to come up with a declaration syntax that both looks better
or is better organised but which is also as comprehensive as C's?

James


James Harris

unread,
Apr 29, 2014, 3:24:02 AM4/29/14
to
"Rod Pemberton" <dont_us...@xnothavet.cqm> wrote in message
news:op.xe11uyjf6zenlw@localhost...
> On Mon, 28 Apr 2014 17:50:34 -0400, James Harris
> <james.h...@gmail.com> wrote:

... (re. C language)

>> What makes it so good to program in despite the faults that
>> people identify?
>
> I think it has two aspects. First, what C gets correct. Second,
> when and where C gets stuff incorrect. Most of the incorrect
> stuff is either trivial, low-use, or on the periphery.
>
> I can identify quite a few and if you've seen my past posts, here,
> a.o.d., a.l.a., c.l.a.x., you're probably aware of some of the many
> faults of C.
>
> So, let's list some (what I recall right now...) of what I think
> C gets correct:

...

I've snipped the list as we are going off topic but we could discuss in a
new thread if you wish. It would be interesting to also see the things you
don't like about C. As mentioned, we wouldn't all agree on what changes we
would want. Maybe that's why of the many derivatives of C few have been
successful.

> It can be argued that many of these features, and others, exist in C
> because the original authors (Kernighan, Ritchie, Thompson) ported
> C to so many different computing platforms and had to redesign the
> language to fit, as many as possible, as cleanly as possible.

I was surprised to see Kernighan's name in there. What was his involvement?

I think you are right that porting a language to many different machines
would have been a big help in identifying essential elements of the language
and, where necessary, in designing features to abstract the differences.

...

> Lack of pointers is a serious problem to have. The Pascal that I learned
> decades ago didn't have them. It was very difficult to solve some
> basic problems without them. I'm not sure how Java etc get around the
> issue.

Not my area but I believe Java allows pointers to objects but disallows
arithmetic on them and, AFAIK, checks array bounds. So while it has pointers
they are not completely flexible; the language stops users pointing at or
referring to memory that the compiler cannot identify. This is not just a
Java feature. These are basic checks. Many languages do similarly. C cannot
check memory accesses as it has no comprehensive way to know what the memory
limits of a bare pointer are.

> Of course, we've since learned that pointers can be very unsafe.

Very! C's allowing pointers to be manipulated by programmers and its
avoiding bounds checking has led to many computer security issues that we
have had over the decades including the current one. It would be hard to
estimate how much money C's pointer model has gained the computer industry
in development savings vs how much it has lost the world due to bugs in
code.

> So, we have a power or flexibility versus safety issue.

Yes, absolutely. Pointers themselves are wonderful in that they solve all
kinds of problems naturally, simply and efficiently. Yet as implemented in C
they are also a liability. Power and responsibility.

James


Nils M Holm

unread,
Apr 29, 2014, 3:52:54 AM4/29/14
to
Rod Pemberton <dont_us...@xnothavet.cqm> wrote:
> I think it's dead. Most people on other newsgroups seem to argue
> against me though when I say language 'X' or 'Y' or 'Z' is dead.
> Other than BASIC, I think the languages of our era (being presumptuous
> here) learned are dead: COBOL, FORTAN, Pascal, LISP, PL/I, Forth,
> Ada, etc. BASIC still seems to have a life in limited situations,
> e.g, industrial machines, hobbyists.

I think it is even worse. Every language todays either looks like C
or it is *wrong*. Because The Industry demands programmers that are
well-trained in C-like languages, and dealing with something that does
not increase your market value is *wrong*. So other languages are only
used by lunatics and academics. This seems to be the consent among
contemporary software developers, and this is sad, because it kills
creativity, diversity, and innovation.

--
Nils M Holm < n m h @ t 3 x . o r g > www.t3x.org

Dmitry A. Kazakov

unread,
Apr 29, 2014, 3:59:45 AM4/29/14
to
On Mon, 28 Apr 2014 21:46:00 -0400, Rod Pemberton wrote:

> So, let's list some (what I recall right now...) of what I think
> C gets correct:
>
> 1) pointers

Since C did almost everything wrong. I will comment only on pointers, which
is also an easy game. What is wrong with them:

1. Pointer types are improperly typed as they are matched by structure.
Thus you cannot have two distinct pointer types for the same target type.
The feature extremely important for building sorted containers and custom
memory pools.

2. Pointers are not initialized with null, as they must for safety reasons.
Neither are they checked for null when dereferenced.

3. Allocator and deallocator are not operations of the pointer type (this
was partially fixed in C++)

4. Pointer arithmetic is a low level hack which should not be there,
because it does not make any sense for variable sized targets or advanced
structures like graphs and trees. It also does not make sense on certain
machine architecture which was and is a huge problem for ones with the
machine word shorter than the physical memory space.

5. Confusing pointers with arrays is a huge problem that caused countless
issues throughout all life time of C. Recent example is OpenSSL.

6. Pointers are easily converted to integers and many C programmers
consider such conversions OK, which leads to extremely fragile and
non-portable code.

7. Each object in C is assumed to be addressable, i.e. the &-operation is
defined on each object. This was tolerable half century ago,
notwithstanding that K&R were seemingly unaware of Boolean and packed
arrays. But now it is a heavy burden with machines of hundreds of registers
and many leveled cache.

That's from the top.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

BartC

unread,
Apr 29, 2014, 4:45:10 AM4/29/14
to
"Rod Pemberton" <dont_us...@xnothavet.cqm> wrote in message
news:op.xe1zoyii6zenlw@localhost...
> On Mon, 28 Apr 2014 12:23:05 -0400, bruce axtens <bugm...@outlook.com>
> wrote:

> As a high-level language, I liked Pascal for the most part. It had
> some wierd stuff in it too though. It was well structured. The problem
> with Pascal, almost three decades ago when I learned it, was it had two
> serious problems. The first was that it didn't have pointers. This
> was safe, but really complicated programming certain solutions. Others
> have pointed out (pun-intended) that Pascal has pointers today.

It certainly had pointers when I used it in the late 70s. What it didn't
have was a proper array type (you had to define fixed bounds for an array,
which made it incompatible with an array with different bounds) and proper
string handling.

> The
> second was that there was no ability to access low-level features of
> the machine. This was a problem in the era of cheap, personal, home
> computers. You were trapped inside a box which couldn't control the
> computer using Pascal.

These problems would have been easy to fix.

--
Bartc

BartC

unread,
Apr 29, 2014, 5:04:53 AM4/29/14
to


"James Harris" <james.h...@gmail.com> wrote in message
news:ljnilc$f30$1...@dont-email.me...
> "BartC" <b...@freeuk.com> wrote in message
> news:57B7v.161805$Qm2.1...@fx16.am4...
>
> ...
>
>> Try this one (an actual requirement I had): you have a pointer to a
>> function
>> (in a dynamic library for example), and it needs N parameters (to keep
>> things simple, they're all of int type). How to call such a function in C
>> without writing N different calls? (Let's say N could be 0 to 12; so 13
>> lots
>> of calls.)
>
> Perhaps I don't understand the requirement properly but wondered if you
> could use the va_arg facilities. They may be unsafe but they are flexible.
> If fp was the function pointer (and assuming that function pointers are
> automartically derefrenced so the preceding * is not needed) could you do
>
> fp(1, parm1);
> fp(5, parm1, parm2, parm3, parm4, parm5);
>
> etc?

I'm not sure. I asked about this in comp.lang.c, and apparently these was no
way to do it in actual C (there is a library which I think I looked at, but
there must have been some issue with it because I just needed up with a
switch statement and dozens of different calls!).

The problem can be expressed better as the implementation of this function:

int call_dll_function (void* fnaddr, int* paramlist, int nparams, int*
result) {
.....
}

So: fnaddr is the address of the function you want to call; paramlist points
to a list of <nparams> int arguments (nparams can be zero, and an upper
limit could be assumed); result is NULL, or a pointer to an int to receive
the result type. It might return some status value.


> Could you not declare variables and constants in your own preferred way?
> You mean it's hard to come up with a declaration syntax that both looks
> better or is better organised but which is also as comprehensive as C's?

No, it's very easy. (Look at the CDECL program, eg.
http://www.lemoda.net/c/cdecl/index.cgi, which translates between C type
specs and English. The English is a left-to-right linear description of the
type. This left-to-right form, or a more compact version (pinched from
Algol-68) is what I use.)

But how to incorporate it into the language? It would need to support both
somehow. But people who are 'into' C apparently aren't bothered with the
that part of it. (Although it begs the question of why someone thought it
necessary to create such a utility as CDECL in the first place!)

--
Bartc

James Harris

unread,
Apr 29, 2014, 6:33:50 AM4/29/14
to
"BartC" <b...@freeuk.com> wrote in message
news:qXJ7v.229545$n%4.3...@fx10.am4...
OK. The problem seems to be that there would be no way for call_dll_function
to issue the call because the number of parameters to a C call has to be
manifest in the source. Good point. I don't know of any language which would
support that except assembly. As you say, a language could have a
"parameter" statement so that calls were made by

parameter 1
parameter 2
...
parameter N
invoke call_dll_function
remove N parameters

Then it would work. (The parameters might need to be stated in the other
direction, i.e. from N down to 1.)

If you wrote the called DLLs they could, instead, get their parameters from
a control block as in

dll1(int *paramlist) {
/* access paramlist[0], paramlist[1], etc */

But if you didn't write the DLLs then your options are limited. That's one
thing I've seen with compilers in general: despite being code generators
they are very poor at interfacing. People don't seem to build in to them the
ability to customise the generated code for specific calls. Instead, the
routines they interface with are expected to adapt to the dictats of the
particular compiler's selected calling convention. Although C is normally
low level its calling sequence is fairly high level and is one thing I would
change: have a default but also allow variants to be indicated where
required.

...

>> Could you not declare variables and constants in your own preferred way?
>> You mean it's hard to come up with a declaration syntax that both looks
>> better or is better organised but which is also as comprehensive as C's?
>
> No, it's very easy. (Look at the CDECL program, eg.
> http://www.lemoda.net/c/cdecl/index.cgi, which translates between C type
> specs and English. The English is a left-to-right linear description of
> the
> type. This left-to-right form, or a more compact version (pinched from
> Algol-68) is what I use.)
>
> But how to incorporate it into the language? It would need to support both
> somehow. But people who are 'into' C apparently aren't bothered with the
> that part of it. (Although it begs the question of why someone thought it
> necessary to create such a utility as CDECL in the first place!)

If you did choose to evolve C into something else you would probably not
want to keep it backwards compatible. If you don't like the existing
declarations surely the purpose is, then, to remove them and replace them
with something better. No point in keeping compatible with something you
dislike.

James


Rod Pemberton

unread,
Apr 29, 2014, 7:33:25 AM4/29/14
to
On Tue, 29 Apr 2014 03:24:02 -0400, James Harris
<james.h...@gmail.com> wrote:
> "Rod Pemberton" <dont_us...@xnothavet.cqm> wrote in message

>> It can be argued that many of these features, and others, exist in C
>> because the original authors (Kernighan, Ritchie, Thompson) ported
>> C to so many different computing platforms and had to redesign the
>> language to fit, as many as possible, as cleanly as possible.
>
> I was surprised to see Kernighan's name in there. What was his
> involvement?
>

K&R C ... What do you think the 'K' and 'R' in K&R are for?

Brian Kernighan and Dennis Ritchie.

Did you mean Ken Thompson? The B language, Unix, and apparently
(I looked this up.) C's ++ -- operators, etc.

> Not my area but I believe [that] Java allows pointers to objects
> but disallows arithmetic on [pointers ...]

That's actually a limitation too. Sometimes you need to do that.
I'd think that linked-lists, binary trees, threaded-code, and even
indexing of arrays or copying of objects would be situations where
that might be used.


Rod Pemberton

Rod Pemberton

unread,
Apr 29, 2014, 7:41:24 AM4/29/14
to
On Tue, 29 Apr 2014 06:33:50 -0400, James Harris
<james.h...@gmail.com> wrote:

> If you did choose to evolve C into something else you would
> probably not want to keep it backwards compatible.

Why wouldn't you?

1) C is everywhere
2) if the C compiler has a preprocessor,
you can do most any syntax conversion
3) C can do everything, or C++ can if C can't,
and C++ was coded in C ...

LOL. ;-)

AISI, the easy place to start is to write your language parser in C.
Yes, you may need to rewrite it in the host language, eventually,
or you could cross-compile.


Rod Pemberton

Jacko

unread,
Apr 29, 2014, 8:37:11 AM4/29/14
to
I'm using free Pascal at the moment. Things I like about it are not having all the makefile and command line stuff getting in the way of doing things. The units feature is very good at this. The IDE is a bit limited, but not so much as to cause real problems. It's all text based, and includes a Free Vision (Turbo Vision clone) for simple text based "GUI" stuff.

It supports various dialects, but the default is just fine. There are a few simplifications (or complications) based around declaring pointer types with self reference, and procedural and functional types, but otherwise quite nice. Minor irritations on naming parameters in forward declarations, and the necessity to use semicolons to separate different typed parameters in definitions, when commas are just as syntax unique.

There are OpenGL units, and quite a few other nice utility units, full unlimited length ANSI strings, and nice object features. It's basically TP7 with some minor syntax changes, and it has support for many cross compilation targets, with a nice c.h file converter.

I like C and Java too, but Java is far too complex to run a fast IDE, and C has very little in the way of controllable error code generation. I try not to use pointers when arrays will do, and consider that a good optimizer will do much of the ++ and the like when appropriate optimization is selected.

Old does not mean useless, in fact I'm very happy to see such a language tool available.

Cheers Jacko

James Harris

unread,
Apr 29, 2014, 9:38:41 AM4/29/14
to
"Rod Pemberton" <dont_us...@xnothavet.cqm> wrote in message
news:op.xe2s1zad6zenlw@localhost...
> On Tue, 29 Apr 2014 03:24:02 -0400, James Harris
> <james.h...@gmail.com> wrote:
>> "Rod Pemberton" <dont_us...@xnothavet.cqm> wrote in message
>
>>> It can be argued that many of these features, and others, exist in C
>>> because the original authors (Kernighan, Ritchie, Thompson) ported
>>> C to so many different computing platforms and had to redesign the
>>> language to fit, as many as possible, as cleanly as possible.
>>
>> I was surprised to see Kernighan's name in there. What was his
>> involvement?
>>
>
> K&R C ... What do you think the 'K' and 'R' in K&R are for?
>
> Brian Kernighan and Dennis Ritchie.

Yes, that's a book! Because the book became so popular some people assume
Kernighan had a hand in writing C but I was sure you would have known that
he did not. I would be interested to hear that he had a hand in porting C
but have never heard of that before. He certainly was not an author of C.

If, on the other hand, by "authors" you meant writing books AFAIK Thompson
has never written any books on C though he may have done.

> Did you mean Ken Thompson? The B language, Unix, and apparently
> (I looked this up.) C's ++ -- operators, etc.

No, I didn't mean him. Thompson was credited with B as Ritchie was credited
with C. I don't know but I can easily believe that Thompson was involved in
porting C. However, for some reason I did not imagine Kernighan being
involved in that.

>> Not my area but I believe [that] Java allows pointers to objects
>> but disallows arithmetic on [pointers ...]
>
> That's actually a limitation too. Sometimes you need to do that.
> I'd think that linked-lists, binary trees, threaded-code, and even
> indexing of arrays or copying of objects would be situations where
> that might be used.

No, under the no-arithmetic-on-pointers model any 'object' can be pointed at
but the pointer stays pointing at the beginning of the object rather than
jumping into it. And offsets within indexable objects can be referred to by
index. So all the structures you mention can be accommodated, albeit not
quite in the same way.

James


Kaz Kylheku

unread,
Apr 29, 2014, 11:51:17 AM4/29/14
to
On 2014-04-29, Dmitry A. Kazakov <mai...@dmitry-kazakov.de> wrote:
> On Mon, 28 Apr 2014 21:46:00 -0400, Rod Pemberton wrote:
>
>> So, let's list some (what I recall right now...) of what I think
>> C gets correct:
>>
>> 1) pointers
>
> Since C did almost everything wrong. I will comment only on pointers, which
> is also an easy game. What is wrong with them:
>
> 1. Pointer types are improperly typed as they are matched by structure.
> Thus you cannot have two distinct pointer types for the same target type.
> The feature extremely important for building sorted containers and custom
> memory pools.

"Extremely" is a hyperbole, since people have developed these things in C
without even so much a fleeting thought such as "I could use pointer type names
based on name equivalence".

> 2. Pointers are not initialized with null, as they must for safety reasons.
> Neither are they checked for null when dereferenced.

C variables in static storage are initialized to null or zero, as the case may
be.

Local variables are not initialized in C, which is a safety issue for any type,
not only pointers. An uninitialized integer could be used as bad index,
relative to a pointer which is initialized. An uninitialized floating-point
value could crash a rocket.

Any decent C compiler has a warnings for uninitialized locals, and any decent
C programmer investigates what diagnostic options are available, and uses
all of them that aren't nuisance stylistic warnings.

It is not difficult to implement the diagnostic: during data flow analysis, the
compiler can identify variable uses which are not preceded by an assignment in
the flow graph. Such cases are either provably uninitialized uses or potential.

> 3. Allocator and deallocator are not operations of the pointer type (this
> was partially fixed in C++)
>
> 4. Pointer arithmetic is a low level hack which should not be there,
> because it does not make any sense for variable sized targets or advanced
> structures like graphs and trees.

Pointer arithmetic is necessary for managing variable-sized targets,
like records that have multiple variant fields, all in the same linear
memory block. These could be stuck into a graph structure.

> It also does not make sense on certain
> machine architecture which was and is a huge problem for ones with the
> machine word shorter than the physical memory space.

The demand for C toolchains killed those architectures, so that's not a problem
any more.

Machines with a word size that cannot address all memory are ... silly.

This is not a "huge problem" in the world; on the contrary, it is a
non-problem, now that cheap 64 bit machines are available to consumers.

> 5. Confusing pointers with arrays is a huge problem that caused countless
> issues throughout all life time of C. Recent example is OpenSSL.

No comment there. The tools and choice of tools and methods does deserve blame
here.

> 6. Pointers are easily converted to integers and many C programmers
> consider such conversions OK, which leads to extremely fragile and
> non-portable code.

Pointers are not easily converted to integers; an incantation is required
to do this: a cast. Without the cast, the conversion is a constraint
violation that requires a diagnostic.

The incantation isn't very verbose. Making it so wouldn't be an impediment
because programmers could use macros to overcome cumbersome incantations. You
could language-built-in macros away from programmers, in which case they could
retort with custom preprocessors and code generation.

What would constitute sufficient difficulty in the integer-pointer conversion?
Sacrificing a goat for each instance?

The code is not fragile and non-portable at the same time. Conversions between
pointers and integers can be completely solid.

Example: the traditional return value of the POSIX function to indicate failure:
-1 cast to (void *). (Nowadays hidden behind the symbol MAP_FAILURE).

Non portable it may be, but there isn't anything "fragile" about it.
Fragility would be demonstrated by breaking, and that would just add up to
non-portability.

Integers cast to pointers are used for memory-mapped I/O registers. This is very
common in operating system kernels and embedded systems.

> 7. Each object in C is assumed to be addressable, i.e. the &-operation is
> defined on each object.

Variables declared "register" cannot have this operation applied to them.

But even without this, the analysis is very easy for determining whether or not
a declared object is subject to the & operator over its scope.

> This was tolerable half century ago,
> notwithstanding that K&R were seemingly unaware of Boolean and packed
> arrays.

Bit-field structure members (a C feature since ANSI C of the 1980's), also
cannot have their address taken.

> But now it is a heavy burden with machines of hundreds of registers
> and many leveled cache.

In fact the trend has been that compilers can work this out.

And so the register storage class specifier has become deprecated.

It's not unusual to see a C compiler completely optimize a variable into
a register, or make it disappear entirely.

Dmitry A. Kazakov

unread,
Apr 30, 2014, 4:57:31 AM4/30/14
to
On Tue, 29 Apr 2014 15:51:17 +0000 (UTC), Kaz Kylheku wrote:

> On 2014-04-29, Dmitry A. Kazakov <mai...@dmitry-kazakov.de> wrote:
>> On Mon, 28 Apr 2014 21:46:00 -0400, Rod Pemberton wrote:
>>
>>> So, let's list some (what I recall right now...) of what I think
>>> C gets correct:
>>>
>>> 1) pointers
>>
>> Since C did almost everything wrong. I will comment only on pointers, which
>> is also an easy game. What is wrong with them:
>>
>> 1. Pointer types are improperly typed as they are matched by structure.
>> Thus you cannot have two distinct pointer types for the same target type.
>> The feature extremely important for building sorted containers and custom
>> memory pools.
>
> "Extremely" is a hyperbole, since people have developed these things in C
> without even so much a fleeting thought such as "I could use pointer type names
> based on name equivalence".

It is not about Turing-completeness of C, it is about pointer design. Yes,
people don't even aware of a possibility to automatically select the memory
pool based on the pointer type. Not possible, per wrong design.

> Any decent C compiler has a warnings for uninitialized locals,

Record fields, dynamically allocated objects?

Anyway, it is a halting problem. Trivially:

int x;
int * y;

if (HALT (p)) y = &x;

So any such check must necessarily generate false negatives or false
positives.

And it is not in C programming culture to pay much attention to silly
compiler warnings, anyway.

> and any decent
> C programmer investigates what diagnostic options are available, and uses
> all of them that aren't nuisance stylistic warnings.

A little problem is that "decent C programmers" according this definition
probably don't exist. It is extremely difficult to hire a good C
programmer.

Anyway, a precaution that can be done by compiler but left to the
programmer is a language design fault, which C pointers are.

>> 4. Pointer arithmetic is a low level hack which should not be there,
>> because it does not make any sense for variable sized targets or advanced
>> structures like graphs and trees.
>
> Pointer arithmetic is necessary for managing variable-sized targets,
> like records that have multiple variant fields, all in the same linear
> memory block. These could be stuck into a graph structure.

No. If you need a pointer to the next element you don't have to compute it.
You just store it. Otherwise, see the position #1. If pointers were
properly designed as ADTs, there would be no problem to define arithmetic
on *some* of them as needed. Instead of that the language enforces blanket
garbage semantics on all of them. Which is a language design fault.

>> It also does not make sense on certain
>> machine architecture which was and is a huge problem for ones with the
>> machine word shorter than the physical memory space.
>
> The demand for C toolchains killed those architectures, so that's not a problem
> any more.

So much for being "close to hardware"!

> This is not a "huge problem" in the world; on the contrary, it is a
> non-problem, now that cheap 64 bit machines are available to consumers.

Well, the balance between the cost of a CPU cycle vs. memory byte has
shifted towards CPU. It is difficult to say whether that will stay so. When
massively parallel architectures will arrive, the model of shared memory
will inevitable die. There is no way to share memory between thousands of
cores. This might shift the balance back, away from flat, isotropic memory
models...

>> 5. Confusing pointers with arrays is a huge problem that caused countless
>> issues throughout all life time of C. Recent example is OpenSSL.
>
> No comment there. The tools and choice of tools and methods does deserve blame
> here.

Ah, but if you need tools on top of the language, that is a language fault
again. Tools is an answer to miserable languages we have to program in.

> What would constitute sufficient difficulty in the integer-pointer conversion?
> Sacrificing a goat for each instance?

Making meaningless conversions unnecessary?

> The code is not fragile and non-portable at the same time. Conversions between
> pointers and integers can be completely solid.
>
> Example: the traditional return value of the POSIX function to indicate failure:
> -1 cast to (void *). (Nowadays hidden behind the symbol MAP_FAILURE).
>
> Non portable it may be, but there isn't anything "fragile" about it.
> Fragility would be demonstrated by breaking, and that would just add up to
> non-portability.

Fragility is when small changes lead to heavy distributed maintenance
overhead in the client code base.

>> 7. Each object in C is assumed to be addressable, i.e. the &-operation is
>> defined on each object.
>
> Variables declared "register" cannot have this operation applied to them.
>
> But even without this, the analysis is very easy for determining whether or not
> a declared object is subject to the & operator over its scope.

So, the program semantics and legality may depend on the outcome of
register optimization? That is again a language design fault.

Kaz Kylheku

unread,
Apr 30, 2014, 11:47:10 AM4/30/14
to
On 2014-04-30, Dmitry A. Kazakov <mai...@dmitry-kazakov.de> wrote:
> On Tue, 29 Apr 2014 15:51:17 +0000 (UTC), Kaz Kylheku wrote:
>
>> On 2014-04-29, Dmitry A. Kazakov <mai...@dmitry-kazakov.de> wrote:
>>> On Mon, 28 Apr 2014 21:46:00 -0400, Rod Pemberton wrote:
>>>
>>>> So, let's list some (what I recall right now...) of what I think
>>>> C gets correct:
>>>>
>>>> 1) pointers
>>>
>>> Since C did almost everything wrong. I will comment only on pointers, which
>>> is also an easy game. What is wrong with them:
>>>
>>> 1. Pointer types are improperly typed as they are matched by structure.
>>> Thus you cannot have two distinct pointer types for the same target type.
>>> The feature extremely important for building sorted containers and custom
>>> memory pools.
>>
>> "Extremely" is a hyperbole, since people have developed these things in C
>> without even so much a fleeting thought such as "I could use pointer type names
>> based on name equivalence".
>
> It is not about Turing-completeness of C, it is about pointer design. Yes,
> people don't even aware of a possibility to automatically select the memory
> pool based on the pointer type. Not possible, per wrong design.

Indeed, C has very little compile-time polymorphism.

(The successor language C++ adds considerable compile-time polymorphism, while
maintaining strong backward compatibility. C++ hasn't completely succeeded in
displacing C.)

>> Any decent C compiler has a warnings for uninitialized locals,
>
> Record fields, dynamically allocated objects?

In C, an aggregate or struct field cannot be individually initialized, such
that others are left uninitialized. If the object has an initializer, all
members are initialized.

The problem of partially initialized objects occurs when objects are
left uninitialized and then configured member by member.

(This is, ironically, a big problem in C++, rather than C. In C++, when you
define a constructor, that constructor takes all responsibility for
initializing an object, and an atomic C-like initialization isn't possible.)

Dynamically allocated objects can be produced by a function that returns all
zero memory, like calloc, or your own wrapper for malloc.

struct foo *p_dynamic_foo = calloc(sizeof *pf, 1);

struct foo local_foo = { 0 }; /* all fields are initialized */

Another technique:

static const struct foo blank_foo; /* "blank" static structure */

struct foo *ptr = malloc(sizeof *pf);

*ptr = blank; /* initialize allocated object by copying the blank */

(This two-step approach avoids relying on a pattern of a all-zero bits
producing 0.0 floating-point values and null pointers.)

> Anyway, it is a halting problem. Trivially:

A perfectly accurate diagnostic is not only equivalent to solving the Halting
problem, but it requires access to functions in external compilation units, and
knowledge whether the function in question is ever called, which could depend
on inputs to the program and events. In other words, it is in fact intractable.

The Halting Problem is primarily of academic importance; it requires that we
have a complete description of the entire program that is to be analyzed, and
its complete input.

But we do not need a perfectly accurate diagnostic for uninitialized variables
in the real world; a suspicion is enough.

> int x;
> int * y;
>
> if (HALT (p)) y = &x;
>
> So any such check must necessarily generate false negatives or false
> positives.

If there is any suspicion that the variable is uninitialized, the case
can be made that it needs to be fixed. If a machine finds it hard to tell
whether the variable is uninitialized, a human being will also find it hard to
tell.

Even if HALT(p) (which is in a library somewhere) always returns true today,
so that the assignment always executes whenever this function is called,
someone could change the defnition of HALT so that it no longer always returns
true. When HALT changes, the above code does not get recompiled.

Generating a rational suspicion is easy; it doesn't require solving the Halting
Problem. If it's obvious that the variable is used uninitialized, emit a
confident diagnostic. Otherwise if it is not obvious that the variable is
initialized, emit a "possibly uninitialized" warning. If your compiler is told
to treat warnings as errors, then the build fails.

There is no reason to have false negatives (neglect to identify suspicious cases).

When we fix the false positive with "int *y = NULL", we are at that point no
worse off than a language which forces this automatically, and we can still
leave variables uninitialized in cases that are obviously safe.

> And it is not in C programming culture to pay much attention to silly
> compiler warnings, anyway.

That is neither here nor there. Every language that has ever been popular has
had attracted the goofballs, and always will. It is a social problem.

> Anyway, a precaution that can be done by compiler but left to the
> programmer is a language design fault, which C pointers are.

Not every precaution that can be done by the compiler *should* be done.

Static checking is bane of programming. Ideally, everything should be dynamic,
especially type and dispatch. Binding should always be as late as possible.

Write in a dynamic language, and leave C for the device drivers, codecs,
OS schedulers, etc.

>>> 4. Pointer arithmetic is a low level hack which should not be there,
>>> because it does not make any sense for variable sized targets or advanced
>>> structures like graphs and trees.
>>
>> Pointer arithmetic is necessary for managing variable-sized targets,
>> like records that have multiple variant fields, all in the same linear
>> memory block. These could be stuck into a graph structure.
>
> No. If you need a pointer to the next element you don't have to compute it.
> You just store it. Otherwise, see the position #1.

But then you're dictating to me the memory layout.

Firstly, I don't like that; I'm the designer of my program, I choose the layout.

Now I can live with dictation of memory representations in a nice, high-level
language (e.g. Lisp: I don't care what a cons cell looks like on the heap).
But I still need a language or sub-language for those cases when I do want to
control the layout.

Secondly, what if this is a third-party memory-mapped file where the layout is
imposed?

When the programming language interferes with implementing third-party
requirements, it's a poor language (at least for the problem domain at hand).

> If pointers were
> properly designed as ADTs, there would be no problem to define arithmetic
> on *some* of them as needed. Instead of that the language enforces blanket
> garbage semantics on all of them. Which is a language design fault.

I've never seen pointer arithmetic happen by accident in C code.
This problem Just Doesn't Happen (TM). (Like, "Oops, how did that completely
pointless ++ get onto that ptr variable? I didn't write that!")

I've seen arithmetic wrongly used, of course, but it was used because the
programmer needed and intended it, which is a different problem. If incrementable
pointers were wrapped in an ADT, then the programmer would have used the ADT
in that situation.

That said, there are pointers in C that do not support arithmetic: pointers
to incomplete types. One incomplete type is void: void * pointers do not
support pointer arithmetic. (Arithmetic on void * is a well-known GNU C
extension that is diagnosed if you tell GCC to stick to ISO C).

Other incomplete types beside "void" are incomplete arrays and incomplete
structure, the latter of which are very useful:

struct foo *p; /* no definition of struct foo in scope */
/* arithmetic on p not allowed */

Pointers to incomplete struct types are often used in library or module API's.
The client doesn't know what struct foo is, and cannot perform arithmetic
on pointers to struct foo. The implementation code, of course, can.

(We are sure on a roll. Let's see what utter basics you don't know about C ...)

>> The demand for C toolchains killed those architectures, so that's not a problem
>> any more.
>
> So much for being "close to hardware"!

"C is close to the hardware" is simply the clueless mantra of those who haven't
ever seen the cover of an ISO standard.

C isn't that close to the hardware. There is no standard way to disable interrupts,
or read register R7, or peek at the return address that goes back to the
caller, or test the arithmetic overflow flag of the CPU, if it has one, ...

Now C is close *enough* to the hardware that low-level-ish operating system
code, including device drivers, can be ported between machines. E.g. a UART
driver developed on x86 Linux can work on MIPS, if the same peripheral chip is
available. Furthermore, that driver is not at any serious disadvantage compared
to one written in assembly language for either processor.

>> This is not a "huge problem" in the world; on the contrary, it is a
>> non-problem, now that cheap 64 bit machines are available to consumers.
>
> Well, the balance between the cost of a CPU cycle vs. memory byte has
> shifted towards CPU. It is difficult to say whether that will stay so. When
> massively parallel architectures will arrive, the model of shared memory
> will inevitable die. There is no way to share memory between thousands of
> cores. This might shift the balance back, away from flat, isotropic memory
> models...

There is no way to share memory between millions of machines on an internet,
yet they all use a TCP/IP stack written in C.

A massively parallel machine with many cores will still have local memories,
with some software that uses them conventionally.

>> What would constitute sufficient difficulty in the integer-pointer conversion?
>> Sacrificing a goat for each instance?
>
> Making meaningless conversions unnecessary?

So what then implements the requirements served by those conversions?
Converting a number to a pointer is something which is used because it is needed.

>>> 7. Each object in C is assumed to be addressable, i.e. the &-operation is
>>> defined on each object.
>>
>> Variables declared "register" cannot have this operation applied to them.
>>
>> But even without this, the analysis is very easy for determining whether or not
>> a declared object is subject to the & operator over its scope.
>
> So, the program semantics and legality may depend on the outcome of
> register optimization?

The register storage class means that taking the address of the object is a
diagnosable constraint violation.

(It is additionally intended to be an optimization hint at the same time,
that access to the object should be fast.)

BartC

unread,
Apr 30, 2014, 1:27:08 PM4/30/14
to


"Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
news:1965jbmywu22u$.9o9wv0bq5csu$.dlg@40tude.net...
> On Mon, 28 Apr 2014 21:46:00 -0400, Rod Pemberton wrote:
>
>> So, let's list some (what I recall right now...) of what I think
>> C gets correct:
>>
>> 1) pointers
>
> Since C did almost everything wrong.

Are you taking account of the fact that C is a low-level language? If not,
then you can argue that any assembly language does everything 'wrong'.

> I will comment only on pointers, which
> is also an easy game. What is wrong with them:
>
> 1. Pointer types are improperly typed as they are matched by structure.
> Thus you cannot have two distinct pointer types for the same target type.
> The feature extremely important for building sorted containers and custom
> memory pools.

If you can't trust yourself to not get the two types mixed up, then you can
wrap the target in a struct type.

> 2. Pointers are not initialized with null, as they must for safety
> reasons.
> Neither are they checked for null when dereferenced.

They often are checked for null (usually by the memory management of the
hardware). Doing an explicit runtime check, except during debugging, would
defeat the purpose of using C in the first place. And there are many pointer
invalid values other than null.

> 6. Pointers are easily converted to integers and many C programmers
> consider such conversions OK, which leads to extremely fragile and
> non-portable code.

Conversion of integers /to/ pointers is more of a problem, or would be in
the hands of a programmer who had no idea what he or she is doing. But
usually there is a reason for it.

> 7. Each object in C is assumed to be addressable, i.e. the &-operation is
> defined on each object. This was tolerable half century ago,
> notwithstanding that K&R were seemingly unaware of Boolean and packed
> arrays. But now it is a heavy burden with machines of hundreds of
> registers
> and many leveled cache.

If an object is legally addressable, that why not make that assumption? The
implementer can take care of that if someone wants to use & on something
(for objects that would otherwise only exist in registers, or not at all).

If you mean packed arrays of bit values, then the language has never allowed
individual bits to be addressable.

--
Bartc

Rod Pemberton

unread,
Apr 30, 2014, 9:28:30 PM4/30/14
to
On Tue, 29 Apr 2014 09:38:41 -0400, James Harris
<james.h...@gmail.com> wrote:
> "Rod Pemberton" <dont_us...@xnothavet.cqm> wrote in message
> news:op.xe2s1zad6zenlw@localhost...
>> On Tue, 29 Apr 2014 03:24:02 -0400, James Harris
>> <james.h...@gmail.com> wrote:
>>> "Rod Pemberton" <dont_us...@xnothavet.cqm> wrote in message

>>>> It can be argued that many of these features, and others, exist in C
>>>> because the original authors (Kernighan, Ritchie, Thompson) ported
>>>> C to so many different computing platforms and had to redesign the
>>>> language to fit, as many as possible, as cleanly as possible.
>>>
>>> I was surprised to see Kernighan's name in there. What was his
>>> involvement?
>>
>> K&R C ... What do you think the 'K' and 'R' in K&R are for?
>>
>> Brian Kernighan and Dennis Ritchie.
>
> Yes, that's a book! Because the book became so popular some people assume
> Kernighan had a hand in writing C but I was sure you would have known
> that
> he did not.

Interesting point. Actually, I never gave it much thought to it. The
books
on C which I recollect did nothing more than mention their names in
passing.
So, I guess that was an assumption on my part since both were named for the
book and unofficial language standard. I've never read K&R C. It seemed
less informative that other books. Was that mentioned in there?

> I would be interested to hear that he had a hand in porting C
> but have never heard of that before. He certainly was not an
> author of C.

I currently only have the handful of C papers Ritchie placed on the
internet to search through for references, and a few others. My C
library (books) has been packed away for many years, except the two
books I've told you about previously.


Rod Pemberton

Dmitry A. Kazakov

unread,
May 1, 2014, 4:18:00 AM5/1/14
to
On Wed, 30 Apr 2014 15:47:10 +0000 (UTC), Kaz Kylheku wrote:

> If there is any suspicion that the variable is uninitialized, the case
> can be made that it needs to be fixed. If a machine finds it hard to tell
> whether the variable is uninitialized, a human being will also find it hard to
> tell.

All this is not needed if the language were properly designed. E.g. using
the principle of safest choice (by default, initialized or not?), require
everything explicitly initialized without default initialization defined
(e.g. for pointers). If the programmer wants to leave a variable not
initialized (once in a year), give him a keyword to state this.

>> Anyway, a precaution that can be done by compiler but left to the
>> programmer is a language design fault, which C pointers are.
>
> Not every precaution that can be done by the compiler *should* be done.

Every, for economical reasons. Debugging is more expensive than design.
Maintenance is more expensive than debugging.

> Static checking is bane of programming. Ideally, everything should be dynamic,
> especially type and dispatch. Binding should always be as late as possible.

On the contrary. Late binding convert bugs into faults, e.g. type error
into constraint violation/message-not-understood etc. This is intolerable
from the software engineering POV.

From the CS POV, there no dynamic languages, only poor static languages.
You cannot have everything dynamic, you must stop the indirection
somewhere. If you put all objects that accept a given operation together,
that would constitute a perfectly static type. If that type is anonymous,
that is a language fault, the type is semantically there.

> Write in a dynamic language, and leave C for the device drivers, codecs,
> OS schedulers, etc.

Which implies that dynamic languages are incomplete. Why should anybody use
such a language. Wouldn't it better to design and use a decent language
instead?

>>>> 4. Pointer arithmetic is a low level hack which should not be there,
>>>> because it does not make any sense for variable sized targets or advanced
>>>> structures like graphs and trees.
>>>
>>> Pointer arithmetic is necessary for managing variable-sized targets,
>>> like records that have multiple variant fields, all in the same linear
>>> memory block. These could be stuck into a graph structure.
>>
>> No. If you need a pointer to the next element you don't have to compute it.
>> You just store it. Otherwise, see the position #1.
>
> But then you're dictating to me the memory layout.

Why? A pointer can point anywhere.

> Secondly, what if this is a third-party memory-mapped file where the layout is
> imposed?

You will need de-/serialize objects as with any other file. Memory-mapped
files is a hack, unless we consider a pure object-oriented OS, without
files, where everything is a persistent object. That would not be for C
anyway, nor for poor old Windows nor Linux.

>>> This is not a "huge problem" in the world; on the contrary, it is a
>>> non-problem, now that cheap 64 bit machines are available to consumers.
>>
>> Well, the balance between the cost of a CPU cycle vs. memory byte has
>> shifted towards CPU. It is difficult to say whether that will stay so. When
>> massively parallel architectures will arrive, the model of shared memory
>> will inevitable die. There is no way to share memory between thousands of
>> cores. This might shift the balance back, away from flat, isotropic memory
>> models...
>
> There is no way to share memory between millions of machines on an internet,
> yet they all use a TCP/IP stack written in C.

So what? You are again confusing completeness in narrow Turing sense with
language design. We are talking about structuring the address space. The
address space of Internet is *not* flat and *not* isotropic. q.e.d.

> A massively parallel machine with many cores will still have local memories,
> with some software that uses them conventionally.

Yes, but the programmer of such systems will care about local memory barely
more than he presently cares about L2-cache.

>>> What would constitute sufficient difficulty in the integer-pointer conversion?
>>> Sacrificing a goat for each instance?
>>
>> Making meaningless conversions unnecessary?
>
> So what then implements the requirements served by those conversions?
> Converting a number to a pointer is something which is used because it is needed.

It is never needed, because there is no proper method of obtaining such
numbers in first place. If the method exist, it is pointer-to-number and
back to pointer conversion. Which raises immediate question why number was
needed as a middleman? Because the language lacks means of handling
pointers as proper types and objects (e.g. in order to serialize them)?

All cases where numbers are converted to pointers are at some I/O boundary
and even then there always exist better ways.

>>>> 7. Each object in C is assumed to be addressable, i.e. the &-operation is
>>>> defined on each object.
>>>
>>> Variables declared "register" cannot have this operation applied to them.
>>>
>>> But even without this, the analysis is very easy for determining whether or not
>>> a declared object is subject to the & operator over its scope.
>>
>> So, the program semantics and legality may depend on the outcome of
>> register optimization?
>
> The register storage class means that taking the address of the object is a
> diagnosable constraint violation.

So must have been the class of addressable objects. If the programmer's
intent is to access the object via pointer, he should declare this in
advance. If he mistakenly takes a pointer to an object that is not intended
for aliasing, this is a serious bug, and must be flagged as such. Bugs
related to aliasing are extremely hard to debug. The principle of safest
choice.

Dmitry A. Kazakov

unread,
May 1, 2014, 4:18:08 AM5/1/14
to
On Wed, 30 Apr 2014 18:27:08 +0100, BartC wrote:

> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
> news:1965jbmywu22u$.9o9wv0bq5csu$.dlg@40tude.net...
>> On Mon, 28 Apr 2014 21:46:00 -0400, Rod Pemberton wrote:
>>
>>> So, let's list some (what I recall right now...) of what I think
>>> C gets correct:
>>>
>>> 1) pointers
>>
>> Since C did almost everything wrong.
>
> Are you taking account of the fact that C is a low-level language? If not,
> then you can argue that any assembly language does everything 'wrong'.

Oh, but this is different. Firstly, of course, you should define the
"level". Presumably it is a level of abstraction away, but from what?

Often repeated proposition that C is close to the hardware = not really
abstracts the machine, is plain wrong. Most of C primitives do not really
match the hardware architecture. In that sense C is by no means low-level.
It is quite high-level in fact. It might have been low-level for PDP, in
the time when the myth was established. There is little low-level in C in
this sense now. C has an assorted set of abstractions, poorly chosen ones.
This alone does make C low level, it does it wrong. Note that an assembly
language does not suffer this problem as it indeed matches the hardware.

If you consider "level" related to some abstract programming paradigm, yes,
C is very low-level because it lacks a lot of things, starting with a
decent type system, means of encapsulation etc. This, again, is not really
comparable to assembly languages. Some of them have higher level features
like macro capacities (AKA generic programming) missing in C. E.g. MACRO-11
assembly was arguably higher level than C in some aspects (and lower in
others).

>> I will comment only on pointers, which
>> is also an easy game. What is wrong with them:
>>
>> 1. Pointer types are improperly typed as they are matched by structure.
>> Thus you cannot have two distinct pointer types for the same target type.
>> The feature extremely important for building sorted containers and custom
>> memory pools.
>
> If you can't trust yourself to not get the two types mixed up, then you can
> wrap the target in a struct type.

But that won't be a pointer anymore.

This is another language fault that you don't have a pointer interface
abstracted. You cannot define a type and dress it as a pointer. But this is
a "second" layer of faults C didn't even close to, because it lacks any
use-defined type altogether.

>> 2. Pointers are not initialized with null, as they must for safety reasons.
>> Neither are they checked for null when dereferenced.
>
> They often are checked for null (usually by the memory management of the
> hardware).

Maybe, but we are talking about the language. Whatever the hardware does or
not is irrelevant. After all C does not have exceptions to deal with
run-time checks.

>> 6. Pointers are easily converted to integers and many C programmers
>> consider such conversions OK, which leads to extremely fragile and
>> non-portable code.
>
> Conversion of integers /to/ pointers is more of a problem, or would be in
> the hands of a programmer who had no idea what he or she is doing. But
> usually there is a reason for it.

Language design fault is that reason.

>> 7. Each object in C is assumed to be addressable, i.e. the &-operation is
>> defined on each object. This was tolerable half century ago,
>> notwithstanding that K&R were seemingly unaware of Boolean and packed
>> arrays. But now it is a heavy burden with machines of hundreds of
>> registers and many leveled cache.
>
> If an object is legally addressable, that why not make that assumption?

Sorry, I cannot decode this. "Legally" means according to the language? If
X is legally addressable, it is not an assumption it is a fact that X is
addressable.

> If you mean packed arrays of bit values, then the language has never allowed
> individual bits to be addressable.

Because it didn't have them. The language designers didn't care, there is
no arrays in C anyway. And since in PDP you indeed could address literally
everything, even a machine register, they, likely, unconsciously projected
this to every machine, if they thought about that, which I doubt.

James Harris

unread,
May 1, 2014, 5:44:15 AM5/1/14
to
"Rod Pemberton" <dont_us...@xnothavet.cqm> wrote in message
news:op.xe5qdsaj6zenlw@localhost...
I don't remember seeing it in K&R2. I thought I had seen a video of
Kernighan saying that he was not involved but I cannot find it. However, I
did find this:

http://www.linuxjournal.com/article/7035

The relevant part is short enough to repeat here

LJ: What was your part in the birth and destiny of the C language?

BK: I had no part in the birth of C, period. It's entirely Dennis Ritchie's
work. I wrote a tutorial on how to use C for people at Bell Labs, and I
twisted Dennis's arm into writing a book with me. But, if he had been so
motivated, he certainly could have done it without help. He's a superb
writer, as one can tell from the C reference manuals, which are his prose,
untouched. I've profited a great deal from being part of the book, and I
treasure Dennis as a friend, but I didn't have anything to do with C.

I don't know about you but this seems to me to be an especially modest
comment. Pure speculation but I could imagine Ritchie speaking more highly
of Kernighan's input, if only in terms of useful feedback on the design.

>> I would be interested to hear that he had a hand in porting C
>> but have never heard of that before. He certainly was not an
>> author of C.
>
> I currently only have the handful of C papers Ritchie placed on the
> internet to search through for references, and a few others. My C
> library (books) has been packed away for many years, except the two
> books I've told you about previously.

Re. porting C I remember hearing a story that Ritchie and Thompson once got
muddled up over who was going to write a certiain small subroutine and they
both wrote it. When they realised what had happened they compared the code
and found the two versions identical! It was because of hearing that that I
could imagine them both being involved in porting C but that is an
assumption on my part.

James


Kaz Kylheku

unread,
May 1, 2014, 12:56:50 PM5/1/14
to
On 2014-05-01, Dmitry A. Kazakov <mai...@dmitry-kazakov.de> wrote:
> On Wed, 30 Apr 2014 15:47:10 +0000 (UTC), Kaz Kylheku wrote:
>
>> If there is any suspicion that the variable is uninitialized, the case
>> can be made that it needs to be fixed. If a machine finds it hard to tell
>> whether the variable is uninitialized, a human being will also find it hard to
>> tell.
>
> All this is not needed if the language were properly designed. E.g. using
> the principle of safest choice (by default, initialized or not?), require
> everything explicitly initialized without default initialization defined

Before C99, C had "declarations before statements" (like "Wirthian" languages).

If declarations have to follow statements, you sometimes have to write
code like this:

int var;

lock(&obj->lock_var);

var = obj->memb;

I wrote something very similar to this just yesterday, inside
a USB driver.

If var had to be initialized, the compiler would still have to do all
the same analysis in order to optimize that away; it would have to
relize that the initial value has no "next use" in the flow graph.

This particular use goe away if we mix variable definitions with statements:

lock(&obj->lock_var);
int var = obj->memb;

This is supported in C starting with C99, and has been in C++ for a long
time (precisely because C++ objects with constructors do not support
this two-step initialization).

>> Static checking is bane of programming. Ideally, everything should be dynamic,
>> especially type and dispatch. Binding should always be as late as possible.
>
> On the contrary. Late binding convert bugs into faults, e.g. type error
> into constraint violation/message-not-understood etc. This is intolerable
> from the software engineering POV.

If you don't formalize late binding into the language, programmers
will reinvent it anyway, in an ad-hoc way.

Dynamic languages are well known for their productivity and robust
applications.

Whenever something falls down in computing, more often than not, some
statically typed trash is at the root cause.

> From the CS POV, there no dynamic languages, only poor static languages.

Complete nonsense. Languages are dynamic by default. All the pseudo-code
in CS textbooks and papers is essentially dynamic.

Statica analysis is just a way of classifying a certain subset of dynamic
programs: those which have the property that a type can be inferred for
every node in their graph (possibly after expanding that graph in the
face of "static polymorphism"), so that no expression has more than one type in
different run-time situations.

(Languages with explicit declarations for determining what type flows
into every node in the graph are obsolete dinosaurs; the state of the
art in static typing is inference.)

> You cannot have everything dynamic, you must stop the indirection
> somewhere.

Reductio ad 1 et 0.

Dynamic languages are supported by a kernel of run-time code that isn't
itself dynamic, and also by compiler generated code that isn't dynamic
either. It just "knows" that, say, two certain bits of a value are a
type tag: no other meta-tag tells it that.

Ultimately, bits are statically typed; we know that a bit cell has type "bit"
and only contains a 1 or 0; there is no need to check some other information to
verify.

> If you put all objects that accept a given operation together,
> that would constitute a perfectly static type.

Sure, a meaningless static type like "Object" which need not be mentioned int
the language.

>> Write in a dynamic language, and leave C for the device drivers, codecs,
>> OS schedulers, etc.
>
> Which implies that dynamic languages are incomplete. Why should anybody use
> such a language. Wouldn't it better to design and use a decent language
> instead?

They aren't. For instance Lisp machines were written entirely in Lisp,
interrupt-driven device drivers and all. There are nice implementatinos
of Lisp with good compilers. Whereas, say, Python or Ruby users call
C libraries for things like regex, crypto or image processing, Lisp
programmers use libraries written in Lisp for this, because the performance
is decent.

People don't write device drivers in Lisp nowadays though because platforms
dictate the methodology for those (so it is usually done in C).

Millions of programmers choose "incomplete" languages that don't even have
compilers, because they find them to be the right tool for the right job. They
have some ready-made framework, library and possibly "recipes" on how to
structure the major pieces together.

They aren't writing an device driver, so they don't care that they cannot.

However, a dynamic language can certainly be the "be all" system language
from the boostrap loader on up.

>>>>> 4. Pointer arithmetic is a low level hack which should not be there,
>>>>> because it does not make any sense for variable sized targets or advanced
>>>>> structures like graphs and trees.
>>>>
>>>> Pointer arithmetic is necessary for managing variable-sized targets,
>>>> like records that have multiple variant fields, all in the same linear
>>>> memory block. These could be stuck into a graph structure.
>>>
>>> No. If you need a pointer to the next element you don't have to compute it.
>>> You just store it. Otherwise, see the position #1.
>>
>> But then you're dictating to me the memory layout.
>
> Why? A pointer can point anywhere.

You're dictating that the pointer is *there* in the layout, rather than just
the next element itself (whereby we calculate the address of the element
ourselves, outside of the structure) That embedded pointer not even directly
possible if that layout is from a memory mapping that can be placed at any
address, and shared by processes.

>> Secondly, what if this is a third-party memory-mapped file where the layout is
>> imposed?
>
> You will need de-/serialize objects as with any other file.

Screw that; I want memory mapped!

> Memory-mapped files is a hack,

That is neither here nor there; they exist, developers sometimes want them.
They have measurable, demonstrable benefits. (As well as shortcomings.)

>>> Well, the balance between the cost of a CPU cycle vs. memory byte has
>>> shifted towards CPU. It is difficult to say whether that will stay so. When
>>> massively parallel architectures will arrive, the model of shared memory
>>> will inevitable die. There is no way to share memory between thousands of
>>> cores. This might shift the balance back, away from flat, isotropic memory
>>> models...
>>
>> There is no way to share memory between millions of machines on an internet,
>> yet they all use a TCP/IP stack written in C.
>
> So what? You are again confusing completeness in narrow Turing sense with
> language design.

I am not confusing anything. I know all all about Turing equivalence not
being expressivity equivalence. (And have had to hit numerous people on
Usenet over the head with that over twenty years.)

I didn't claim that C is an expressive language for writing an application
for a thousand cores that do not share memory well.

However, I think C will will end up used for programming parts of that system,
and perhaps even parts of the run-time support for whatever language is used
at the high level for harnessing those cores.

That machine will still need to to mundane things like boot up, or
push packets to and from some ethernet controller with DMA and interrupts,
etc.

C you there! :)

> We are talking about structuring the address space. The
> address space of Internet is *not* flat and *not* isotropic. q.e.d.

But you can get 64 kilobyte pieces of thanks to a popular C library! :)

>> A massively parallel machine with many cores will still have local memories,
>> with some software that uses them conventionally.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

See, some software: not all.

> Yes, but the programmer of such systems will care about local memory barely
> more than he presently cares about L2-cache.

The programmers of some kinds of applications already don't care about this
on boxes with just a handful of cores (perhaps one).

>>>> What would constitute sufficient difficulty in the integer-pointer conversion?
>>>> Sacrificing a goat for each instance?
>>>
>>> Making meaningless conversions unnecessary?
>>
>> So what then implements the requirements served by those conversions?
>> Converting a number to a pointer is something which is used because it is needed.
>
> It is never needed, because there is no proper method of obtaining such
> numbers in first place.

Yes there is; system documentation, data sheets.

> If the method exist, it is pointer-to-number and
> back to pointer conversion. Which raises immediate question why number was
> needed as a middleman?

Simply for the pragmatic reason that addresses on digital, binary computers are
numbers.

This can be abstracted away for objects that need not have a concrete,
particular address.

> All cases where numbers are converted to pointers are at some I/O boundary
> and even then there always exist better ways.

No, not all cases have to do with I/O.

Sometimes C programs use "spare bits" in pointers for additional information.

Some concurrent algorithms rely on this (like lock-free linked lists), and also
implementations of dynamic languages that are written in C.

Tn the implementation of the TXR language, every value is a C pointer
of type val, which is a typedef for obj_t *.

Pointers are relied upon to have an alignment of at least four bytes,
which leaves the least significant two bits open for use as a type tag.

So "fixnum" integers can be represented directly inside the pointer
value, as well as characters.

The tag is chosen such that the value 0 (bits 00) denote a heaped object.
That means that the pointer can be dereferenced directly.

>>>>> 7. Each object in C is assumed to be addressable, i.e. the &-operation is
>>>>> defined on each object.
>>>>
>>>> Variables declared "register" cannot have this operation applied to them.
>>>>
>>>> But even without this, the analysis is very easy for determining whether or not
>>>> a declared object is subject to the & operator over its scope.
>>>
>>> So, the program semantics and legality may depend on the outcome of
>>> register optimization?
>>
>> The register storage class means that taking the address of the object is a
>> diagnosable constraint violation.
>
> So must have been the class of addressable objects. If the programmer's
> intent is to access the object via pointer, he should declare this in
> advance. If he mistakenly takes a pointer to an object that is not intended
> for aliasing, this is a serious bug, and must be flagged as such.

The Wirthian language commit a serious offense in this regard compared to C.
In Pascal and its ilk, you can change a procdure's conventional by-value
argument to a VAR argument. When the program is recompiled, calls to that
procedure now silently "steal" references to variables and may modify them.

C++ also has this in the form of references.

In C we at least have a loud and clear syntax that the address is being
taken: the & operator (though it can be hidden behind a macro).

Having to explicitly declare a permission for an address to be taken isn't such
a bad idea, but it can have downsizes. For instance, your program could really
benefit from taking the address of a variable in some third-party library.
Ooops, it is not declared for that!

In C we have the const qualifier whose behavior is such that the address of a
const qualified object is a pointer to a const-qualified type. When this
pointer is dereferenced, the resulting lvalue cannot be assigned; it is not
modifiable. This provides a reasonable middle ground: allow the address, but
one that gives rise to only read-only aliases.

> Bugs
> related to aliasing are extremely hard to debug. The principle of safest
> choice.

If that's the best way to write the program, then it is no harder to debug
than it has to be.

Kaz Kylheku

unread,
May 1, 2014, 1:10:29 PM5/1/14
to
On 2014-05-01, Dmitry A. Kazakov <mai...@dmitry-kazakov.de> wrote:
> On Wed, 30 Apr 2014 18:27:08 +0100, BartC wrote:
>
>> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
>> news:1965jbmywu22u$.9o9wv0bq5csu$.dlg@40tude.net...
>>> On Mon, 28 Apr 2014 21:46:00 -0400, Rod Pemberton wrote:
>>>
>>>> So, let's list some (what I recall right now...) of what I think
>>>> C gets correct:
>>>>
>>>> 1) pointers
>>>
>>> Since C did almost everything wrong.
>>
>> Are you taking account of the fact that C is a low-level language? If not,
>> then you can argue that any assembly language does everything 'wrong'.
>
> Oh, but this is different. Firstly, of course, you should define the
> "level". Presumably it is a level of abstraction away, but from what?

As a starting point, a good "rough" definition of a low level of abstraction
means that programs for diverse appliactions look the same.

If I look at the insides of a text editor, cryptographic library, image
recognition, device driver, or game, and they all look like approximately the
same cruft (for instance a column of machine language instructions), then they
are at a low level of abstraction compared to their application domains.

A very good definition of Abstraction Level comes from the Tunes project:

http://tunes.org/wiki/abstraction_20level.html

Especially the criterion in the last paragraph.

"A set of programs is more high-level than another one if for each problem
solved by the second set of programs, there exist a higher-level program that
solves the same problem in the first set."

A "program" can be taken to represent not necessarily an executable sitting
on your disk, but a procedure, machine language instruction or any capsule
of computation.

So the criterion explains why machine language is low level. For any given
problem solved using machine language, the same "set of programs" is applied:
the same bag of machine instructions. This is why the solutions look the same.
If I see 25 lines of disassembly listing, I have no clue whether I'm looking at
a text editor, device driver, or image recognition code, since it's just a
combination of the "programs": the little routines in the instruction set like
"compare that register to that other one".

> Often repeated proposition that C is close to the hardware = not really
> abstracts the machine, is plain wrong. Most of C primitives do not really
> match the hardware architecture. In that sense C is by no means low-level.

Level is really a lattice. There is some ideal awy of expressing what I'm
doing. And multiple, though diverse, directions away from that are "lower
level".

Processing data with Unix piping and text manipulation is often at an
inappropriate level for that data. It's low-level in some sense in that it
never gets away from the irrelevant details of how the printed representation
of the data is delimited, and the code doesn't really express whatis going
on; it just says "I'm a mass of shell cruft that has to be read in painstaking
detail to decode what is going on".

Dmitry A. Kazakov

unread,
May 2, 2014, 3:22:24 AM5/2/14
to
On Thu, 1 May 2014 17:10:29 +0000 (UTC), Kaz Kylheku wrote:

> On 2014-05-01, Dmitry A. Kazakov <mai...@dmitry-kazakov.de> wrote:
>> On Wed, 30 Apr 2014 18:27:08 +0100, BartC wrote:
>>
>>> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
>>> news:1965jbmywu22u$.9o9wv0bq5csu$.dlg@40tude.net...
>>>> On Mon, 28 Apr 2014 21:46:00 -0400, Rod Pemberton wrote:
>>>>
>>>>> So, let's list some (what I recall right now...) of what I think
>>>>> C gets correct:
>>>>>
>>>>> 1) pointers
>>>>
>>>> Since C did almost everything wrong.
>>>
>>> Are you taking account of the fact that C is a low-level language? If not,
>>> then you can argue that any assembly language does everything 'wrong'.
>>
>> Oh, but this is different. Firstly, of course, you should define the
>> "level". Presumably it is a level of abstraction away, but from what?
>
> As a starting point, a good "rough" definition of a low level of abstraction
> means that programs for diverse appliactions look the same.
>
> If I look at the insides of a text editor, cryptographic library, image
> recognition, device driver, or game, and they all look like approximately the
> same cruft (for instance a column of machine language instructions), then they
> are at a low level of abstraction compared to their application domains.

And why is it lower level? If the programs look same, that presumes that
means they deploy are suitable for solving diverse problems (or that the
computational power of the observer (human) is not suitable to distinguish
them properly).

This can be both lower and higher level. It depends on how the observed
uniformity was achieved. If it was through generalization, that would be
higher level. If it was through decomposition into lower-level primitives
it could be lower level. As an extreme example consider a program in the
God's language:

Do it!

Is it low or high level?

> A very good definition of Abstraction Level comes from the Tunes project:
>
> http://tunes.org/wiki/abstraction_20level.html
>
> Especially the criterion in the last paragraph.
>
> "A set of programs is more high-level than another one if for each problem
> solved by the second set of programs, there exist a higher-level program that
> solves the same problem in the first set."

This is merely a constraint to make things comparable, because it would
make no sense to talk about a "higher-level" thing that does not solve the
problems of interest in first place.

> A "program" can be taken to represent not necessarily an executable sitting
> on your disk, but a procedure, machine language instruction or any capsule
> of computation.
>
> So the criterion explains why machine language is low level. For any given
> problem solved using machine language, the same "set of programs" is applied:
> the same bag of machine instructions. This is why the solutions look the same.
> If I see 25 lines of disassembly listing, I have no clue whether I'm looking at
> a text editor, device driver, or image recognition code, since it's just a
> combination of the "programs": the little routines in the instruction set like
> "compare that register to that other one".

No. You just said that human sensing operates a language different from
machine language. Which is why a human has difficulty recognizing meaning
of machine code. There is nothing *here*, that makes machine language lower
level.

Dmitry A. Kazakov

unread,
May 2, 2014, 4:10:35 AM5/2/14
to
On Thu, 1 May 2014 16:56:50 +0000 (UTC), Kaz Kylheku wrote:

> On 2014-05-01, Dmitry A. Kazakov <mai...@dmitry-kazakov.de> wrote:
>> On Wed, 30 Apr 2014 15:47:10 +0000 (UTC), Kaz Kylheku wrote:
>>
>>> Static checking is bane of programming. Ideally, everything should be dynamic,
>>> especially type and dispatch. Binding should always be as late as possible.
>>
>> On the contrary. Late binding convert bugs into faults, e.g. type error
>> into constraint violation/message-not-understood etc. This is intolerable
>> from the software engineering POV.
>
> If you don't formalize late binding into the language, programmers
> will reinvent it anyway, in an ad-hoc way.

Sure, but that does not change the point: bind as early as you can. If the
earliest possible point is run-time, be it so.

> Dynamic languages are well known for their productivity and robust
> applications.

Just wait they arrive in your car's ECU...

>> If you put all objects that accept a given operation together,
>> that would constitute a perfectly static type.
>
> Sure, a meaningless static type like "Object" which need not be mentioned int
> the language.

The Universe as a whole is a meaningless thing.

>>> Write in a dynamic language, and leave C for the device drivers, codecs,
>>> OS schedulers, etc.
>>
>> Which implies that dynamic languages are incomplete. Why should anybody use
>> such a language. Wouldn't it better to design and use a decent language
>> instead?
>
> They aren't. For instance Lisp machines were written entirely in Lisp,
> interrupt-driven device drivers and all. There are nice implementatinos
> of Lisp with good compilers. Whereas, say, Python or Ruby users call
> C libraries for things like regex, crypto or image processing, Lisp
> programmers use libraries written in Lisp for this, because the performance
> is decent.
>
> People don't write device drivers in Lisp nowadays though because platforms
> dictate the methodology for those (so it is usually done in C).

Thus dynamic language are unsuitable for the existing computational strata.
You have a choice, either you change the hardware (where are infamous
Lisp-machines?) or you ditch garbage languages.

> Millions of programmers choose "incomplete" languages that don't even have
> compilers, because they find them to be the right tool for the right job.

Millions of programmers are unqualified for the job. And the industry of
software design as a whole is a joke, for numerous reasons from economical
and legal to the sad fact that software development is not really
engineering and CS is not a science.

>>>>>> 4. Pointer arithmetic is a low level hack which should not be there,
>>>>>> because it does not make any sense for variable sized targets or advanced
>>>>>> structures like graphs and trees.
>>>>>
>>>>> Pointer arithmetic is necessary for managing variable-sized targets,
>>>>> like records that have multiple variant fields, all in the same linear
>>>>> memory block. These could be stuck into a graph structure.
>>>>
>>>> No. If you need a pointer to the next element you don't have to compute it.
>>>> You just store it. Otherwise, see the position #1.
>>>
>>> But then you're dictating to me the memory layout.
>>
>> Why? A pointer can point anywhere.
>
> You're dictating that the pointer is *there* in the layout, rather than just
> the next element itself (whereby we calculate the address of the element
> ourselves, outside of the structure)

"next element itself" is a much stricter dictate and implementation burden.
If it weren't so, and you could always have "the next thing", just as you
wanted, you would be no need pointers in first place!

>>> Secondly, what if this is a third-party memory-mapped file where the layout is
>>> imposed?
>>
>> You will need de-/serialize objects as with any other file.
>
> Screw that; I want memory mapped!

How do you ensure that object's representation in the memory is same?

Deserialization is a process of doing this. Your pointer arithmetic is
deserialization of pointer object from some numeric media. What you argue
for, is merely performing deserialization each time you access serialized
(as a number) pointer. Not always the best strategy.

>>>>> What would constitute sufficient difficulty in the integer-pointer conversion?
>>>>> Sacrificing a goat for each instance?
>>>>
>>>> Making meaningless conversions unnecessary?
>>>
>>> So what then implements the requirements served by those conversions?
>>> Converting a number to a pointer is something which is used because it is needed.
>>
>> It is never needed, because there is no proper method of obtaining such
>> numbers in first place.
>
> Yes there is; system documentation, data sheets.

That does not require either pointer or conversions. E.g. in Ada

type Processor_Status_Register is record ...; -- Whatever

PS : Processor_Status_Register;
for PS'Address use 16#FFFF_FFAC#; -- No pointers, no conversions

>> If the method exist, it is pointer-to-number and
>> back to pointer conversion. Which raises immediate question why number was
>> needed as a middleman?
>
> Simply for the pragmatic reason that addresses on digital, binary computers are
> numbers.

No, they are not. The proper statement is that there exist mappings address
to number and back. Which mapping is not even a bijection, on most
machines.

Merely fact that finiteness of any computer allows you to map anything
there to number does not make anything number. In that sense any program is
integer. Does that help?

>> All cases where numbers are converted to pointers are at some I/O boundary
>> and even then there always exist better ways.
>
> No, not all cases have to do with I/O.
>
> Sometimes C programs use "spare bits" in pointers for additional information.

But these are not *numbers*. These are records, bit-fields etc.

>>>>>> 7. Each object in C is assumed to be addressable, i.e. the &-operation is
>>>>>> defined on each object.
>>>>>
>>>>> Variables declared "register" cannot have this operation applied to them.
>>>>>
>>>>> But even without this, the analysis is very easy for determining whether or not
>>>>> a declared object is subject to the & operator over its scope.
>>>>
>>>> So, the program semantics and legality may depend on the outcome of
>>>> register optimization?
>>>
>>> The register storage class means that taking the address of the object is a
>>> diagnosable constraint violation.
>>
>> So must have been the class of addressable objects. If the programmer's
>> intent is to access the object via pointer, he should declare this in
>> advance. If he mistakenly takes a pointer to an object that is not intended
>> for aliasing, this is a serious bug, and must be flagged as such.
>
> The Wirthian language commit a serious offense in this regard compared to C.

Nope. C's parameters are broken, you should never be able to update an
immutable input parameter. If the parameter is mutable, that must have an
effect on the caller. Either this or that, by-copy vs. by-value is
irrelevant.

But the point stands: pointers introduce aliasing per intent and making all
objects capable of being aliased is a language design fault.
0 new messages