validity of ... reasons for preferring C over C++

Stephen F. Zeigler reported in 1995 on an empirical study, done within Rational Software Corporation, of a large set of C and Ada modules being developed and maintained by the same team, with the same people working on both C and Ada modules.

The rate of defects/KSLOC was 0.676 for the C modules, and 0.096 for the Ada modules - about 7 times more defects per line in C than in Ada.

The study makes many other interesting comparisons:

formatting link

--
Niklas Holsti 
Tidorum Ltd 
 Click to see the full signature
Reply to
Niklas Holsti
Loading thread data ...

In my experience (not with Ada) is that requiring extra information (that aids mechanical checking) is a net benefit.

The major disadvantage of "extra verbiage" is that the advantages are lost in cases in which it is automatically inserted or the programmer does "whatever is necessary to shut the compiler up". Nothing can help in that latter case.

The extra information enables the toolset to be much more helpful when exploring/understanding the code, when refactoring the code, and when writing the code. "Autocomplete" operations largely remove the disadvantage of "extra verbiage".

Reply to
Tom Gardner

Without commenting on Ada specifically, my experience is that the more information you can give the compiler via the source code, the better the environmental tools can help you.

I started with C when the state of the art was multiple green screens, emacs and grep.

The power of modern environments with modern languages to recursively and accurately "show me everything that can call this method" and "show me everything reachable from here", plus "what methods can I call on variable x" is remarkable and helpful.

For me that's a good tradeoff.

And, of course, that extends beyond mere names!

Reply to
Tom Gardner

I believe they used the AdaMagic compiler from SofCheck

formatting link
However, SofCheck has merged with AdaCore, and it seems the Ada-to-C translator is no longer available -- darn. Perhaps is AdaCore gets many requests...

There seems to be another such translator by MapuSoft,

formatting link

If the VTC cubesat was done in SPARK, they probably did not use tasking.

For the MapuSoft translator, they claim to support several real-time kernels, and claim to support all of Ada 83 and Ada 95, but the easily viewable descriptions of the translator do not mention tasking and run-times explicitly.

--
Niklas Holsti 
Tidorum Ltd 
 Click to see the full signature
Reply to
Niklas Holsti

(snip)

Reminds me that Java requires the compiler to be able to determine that a scalar variable is given a value before it is referenced. They could have just zeroed all of them, but that is pretty much your "automatic". This way, you have a chance to think about it. But then again, you can just put =0 on all your declarations.

Yes, another chance to think about the problem, and possible mistakes.

-- glen

Reply to
glen herrmannsfeldt

No.

If a primitive (int, long, boolean etc) isn't explicitly initialised then it is given a sensible default value (0, false etc).

Unless explicitly initialised an object also has a sensible default value, null. There's nothing in the compiler that will prevent you trying to "use" the object, but at runtime a NullPointerException is thrown and, if not caught, a stacktrace.

I've seen projects where NullPointerExceptions were regularly thrown, caught, and ignored. I didn't like it one little bit, but since it was a "contractual obligation" project and the program continued to work, there was no point in my making a great big fuss.

I'm not sure whether or not to be comforted that the program continued to work :)

There's a story from the early Smalltalk days. Someone was bringing up a VM and everything was working except that scrollbars on windows worked in the opposite direction. Eventually it was traced to a VM primitive bug in the subtraction of negative numbers.

On even days I think that illustrates remarkable robustness. On odd days I wonder how anyone could be sure that all VM bugs had been found.

Reply to
Tom Gardner

Let the flames roar! :-)

However, I will focus all my fire on C. I don't know enough about C++ to debate its merits.

You may be surprised by the comparisons later in this post.

Really? If you mean the repetition of "if" in the construct "if" .. "end if" and the similar repetitions of "loop", "case", and "record" in "end loop", "end case", "end record", I believe many programmers find them quite useful, compared to the multiply overloaded meanings of "}" in C. They help an Ada compiler give sensible error messages when some "end" is omitted by mistake.

The only places where you repeat things in Ada, and you do not need to repeat in C, that I can think of now, happen when you want to define the internal codes used for enumeration values or the bit-fields used for structs ("records" in Ada). In C you can specify those without repeating the name of the enumeration literal, or the name of the struct field; in Ada those are repeated, because the "representation clause" is a separate syntactic unit.

C: typedef enum {red = 4, blue = 6, green = 9} color_t;

Ada:

type color_t is (red, blue, green); for color_t use (red => 4, blue => 6, green => 9);

To reduce repetition, the second Ada line can be written as

for color_t use (4, 6, 9);

but that loses the close connection between the name and the corresponding value, and is therefore seldom used.

The languages certainly have a different textual appearance. But I will stick my neck out and argue that for all but small toy programs, Ada is

*less* verbose than C.

How should we measure verbosity? By the number of non-blank characters in the source-code file, or by the number of syntactical tokens? I think both measures are relevant.

If we measure by syntactical tokens, for comparable language constructs there is usually little difference between Ada and C, and in some cases the Ada form is shorter. Let's look at some common examples, assuming that in each case the length of the user-chosen identifiers are the same in Ada and in C (I will argue later below that Ada identifiers should in general be *shorter* than C identifiers, assuming equivalent naming conventions).

The C forms below follow the usual recommendations for always using {} in control structures and "break" in switch cases. In both Ada and C I insert more spaces than usual, around separators, to make it easier to count tokens.

Preparing to use another module

C: # include "sorting.h" Ada: with Sorting ;

Same number of tokens. Ada is 7 characters shorter.

Typeless number definition

C: # define NUM_FROOS 55 Ada: Num_Froos : constant := 55 ;

C is shorter by 2 tokens and 5 characters.

Typed constant definition

C: const float x = 33.4f ; Ada: x : constant float := 33.4 ;

C is shorter by 1 token and 5 characters.

Variable declaration

C: float x ; Ada: x : float ;

C is one character and token shorter.

Type declaration (type naming)

C: typedef float voltage_t ; Ada: subtype voltage_t is float ;

C is one token and 2 characters shorter.

Assignment statement

C: varname = expression ; Ada: varname := expression ;

Same number of tokens; one character less in C.

Assignment to a variable through a pointer

C: * varname = expression ; Ada: varname . all := expression ;

C is one token and 4 characters shorter.

Assignment to a field of a structure through a pointer to the structure

C: varname -> field = expression ; Ada. varname . field := expression ;

Same number of tokens and characters in C and Ada.

Conditional statement

C: if ( condition ) { statements1 } else { statements2 }

Ada: if condition then statements1 else statements2 end if ;

Ada is shorter by two tokens (if we consider "end if" as two tokens) but longer by 4 characters, mainly because of the full-length words in "then" and "end if".

Counted loop from 1 to N

C: for ( int i = 1 ; i 8;

Well, some programmers prefer to avoid automatic conversions.

In Ada, you can control whether conversions are automatic or must be explicit, by using subtypes in the former case and types in the latter case.

If you declare Day_type not as a type, but as a subtype:

subtype Day_type is Integer range 1 .. 31;

you are free to write computations that mix Integer and Day_type, you can assign a Day_type variable to an Integer variable, and can assign an Integer expression to a Day_type variable (with, in the last case, an automatic check that the value is in the range 1 .. 31). However, you can still use Day_type'First and Day_type'Last to ask about the range, and you can loop over all days by

for D in Day_type loop ... end loop;

The code can be shorter, yes. Whether is is clearer is subjective, of course.

Ada compilers these days give you a choice of run-times, from zero-run-time to the full standard, with the corresponding restrictions in the Ada code you can execute on that run-time. For the GNAT compiler, the run-time is treated as a normal library at link-time, so any run-time function that is not used can be eliminated from the executable.

And *of course* the run-time checks can be turned off globally or locally, by compiler options or specific pragmas.

Benchmarks vary, but if one writes Ada code that is functionally equivalent to C code (does not compute with dynamically sized objects, does not use tasking, does not use exceptions, disables run-time checks, etc.) one can expect to have close to the same machine code as for the C code. Note that this does not mean "writing C in Ada", because one still has all the compile-time goodies of Ada: module system, stronger typing, object and type attributes, and so on. And the ability to test the program with run-time checks *on*.

--
Niklas Holsti 
Tidorum Ltd 
 Click to see the full signature
Reply to
Niklas Holsti

Hmm... seems not to be the case.

The Java Specification I found says, in

formatting link

The default initialisation rules, earlier on the same page, do not apply to local variables.

--
Niklas Holsti 
Tidorum Ltd 
 Click to see the full signature
Reply to
Niklas Holsti

Indeed. I wonder why it is required in that subset of cases. Probably something to do with local classes, which were introduced "relatively recently".

This isn't something that concerns me in that the environment requires me to do something that I ought to be doing anyway: it is the safe option without any penalties.

Having said that, I am becoming concerned that Java is becoming unnecessarily complex merely in order to save a few keystrokes, to give computer scientists something to do, and to enable marketeers to brag about "improvements". Local classes were one example, generics another, and the stuff in Java 8 another.

Reply to
Tom Gardner

And in addition, if the goal of the loop is to iterate over the whole of (say) an array, Ada's 'Range attribute can be used so there's no need to explicitly list the loop boundaries within the for statement.

Simon.

--
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP 
Microsoft: Bringing you 1980s technology to a 21st century world
Reply to
Simon Clubley

It is still available, even if they don't advertise it.

AdaMagic has a (supposedly) full Ada runtime written in C. How much of it is included depends on how much is used and how good the C compiler for the target is at eliminating unused code.

I've never seen the VTC team mention RavenSPARK (i.e. SPARK with tasking), so that is probably true. And as they have proved the absence of exceptions, there isn't much runtime use left (if any).

Greetings,

Jacob

--
The backhoe is the natural predator of the fiber optic cable.
Reply to
Jacob Sparre Andersen

That's the main problem - and that's why I say such extra types work both ways.

I would like C and C++ to have a way to specify a ranged subtype, and do compile-type checking on them when possible. But overuse of them - as is encouraged (but by no means required) by Ada and Ada tutorials - leads to extra code to "shut the compiler up". I have had the same problem in Pascal when trying to "do the right thing" regarding types, using explicitly ranged types when possible. The result of the extra code for all the necessary conversions is not just that it makes the code more verbose, with extra places to make mistakes. If you later change something in the types or other parts of the code, the explicit conversions hinder the compiler in spotting possible errors, because you have told it firmly that you know what you are doing.

Reply to
David Brown

I'm snipping the rest of your post, because I am going to need to read up about Ada again before I can reply properly - the little Ada I learned was too long ago for me to give you a proper argument. But so far I can see that it looks like Ada is not as verbose as I believed, and is certainly worth considering more closely.

Reply to
David Brown

Oh yes, I now remember one common place where Ada needs repetition: Ada does not have the combinations of assignment and operation, such as +=, that C provides. So where one can increment a C variable by x += 1, or x++, or ++x, in Ada one must write x := x + 1, or define one's own increment procedure and write inc(x). Same for decrement and other arithmetic operations.

Moreover, Ada does not have the "" operators for left and right shifts; they are functions in the library package Interfaces, called Shift_Left and other verbose names.

--
Niklas Holsti 
Tidorum Ltd 
 Click to see the full signature
Reply to
Niklas Holsti

I did. Here, I'll even respond to some of it:

were all you needed in the 80. How long are the modern equivalents?

K&R C massively under-specified the language, even with the extension of Traps and Pitfalls. The modern specifications fill out the missing bits, and specify the changes that were needed to the language to handle the extensive problems that were exposed.

I never said that C or C++ were "nice" or "friendly" languages - in fact I agree with Niklas' response entirely. C is important because it's "sharp", and some of C++'s features are arguably unnecessary because they don't refine that core concept.

You have to learn how to use it. Much of C++ is entirely suitable for writing effective programs that do their job succinctly, precisely and with a minimum of bloat. The libraries are definitely not designed for the embedded environment, so if you skip them (or use them only with careful circumspection) you'll do better, but the libraries are not the language.

Reply to
Clifford Heath

One argument in favour of verbosity is that it increases the "distance" between distinct, valid programs, thus reducing the probability that a typo will go unnoticed.

A good example of this is to consider two fragments of C code:

A: if (condition) { ... }

B: if (condition); { ... }

The syntactic difference is a semicolon; the semantic difference is vast.

In C, a statement is a statement: anywhere a statement can appear,

*any* statement can appear.

A similar issue arises for expressions. In particular, assignment (=) and equality comparison (==) are both expressions, and can appear almost anywhere that any expression can appear. The fact that there's no distinct boolean type doesn't help here (nor if you confuse & with && or | with ||).

Reply to
Nobody

Here's an old article comparing development costs between C vs Ada:

formatting link
And here's a guide to Ada for C and C++ programmers:

formatting link

Both are somewhat out of date (they are way before Ada 2012) and both are from a pro-Ada perspective, but I found them interesting.

Reply to
Paul Rubin

...

I'm curious to know why you feel that the Zeigler article is from a "pro-Ada perspective". To me it seems that the article tries hard to understand what reasons, other than the language, could explain the differences it reports, such as different competence of programmers, different complexity of modules, etc.

The study was indeed done within a company that developed and sold Ada compilers, but it also sold C and C++ compilers, I believe, so I wouldn't automatically assume a bias.

--
Niklas Holsti 
Tidorum Ltd 
 Click to see the full signature
Reply to
Niklas Holsti

Well, ok, I got both links from a pro-Ada site (adahome.com). It's been a while since I read the Ziegler article but its conclusion was favorable to Ada.

Reply to
Paul Rubin

"AdaHome is (sadly) a zombie site. Its accessible by not updated in well over a decade. It is sometimes useful as an archive of old stuff. A better place to start today is

formatting link

Reply to
britt.snodgrass

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.