473,467 Members | 1,951 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Teaching new tricks to an old dog (C++ -->Ada)

I 'm following various posting in "comp.lang.ada, comp.lang.c++ ,
comp.realtime, comp.software-eng" groups regarding selection of a
programming language of C, C++ or Ada for safety critical real-time
applications. The majority of expert/people recommend Ada for safety
critical real-time applications. I've many years of experience in C/C++ (and
Delphi) but no Ada knowledge.

May I ask if it is too difficult to move from C/C++ to Ada?
What is the best way of learning Ada for a C/C++ programmer?

Jul 23 '05
822 28879
REH

"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:1112022773.497341@athnrd02...
In C++ you can always do:

#include <new>
class SomeClass
{
};
void somefunc()
{
unsigned char obj[sizeof(SomeClass)];

SomeClass *p= new(obj)SomeClass;

delete p;
}
as also:
#include <new>
class SomeClass
{
};
SomeClass *somefunc()
{
static unsigned char obj[sizeof(SomeClass)];

return new(obj)SomeClass;
}
int main()
{
SomeClass *p= somefunc();

delete p;
}
Here the object is created in the stack.
--
Ioannis Vranos

These will mostly fail on systems with alignment constraints (SPARC, PPC,
etc.).

Jul 23 '05 #751

Ioannis Vranos <iv*@remove.this.grad.com> writes:
Pascal Obry once made an interesting remark: what is important for the
safety of a language is not what it allows but what it forbids.

You can't protect a bad programmer from doing bad programming, unless you
forbid him to continue programming. :-)


But you can propose a easy path that is safer. In this case there is lot of
more chance than the programmer will choose it. Easier is always appreciated :)
And a language must make it harder to do unsafe thing, like deallocation on
Ada. You have a instanciate Unchecked_Deallocation. The meaning is clear and
nobody can do that without noticing.

As Ludovic I appreciate a lot the help of the compiler and never try to fight
it. If it tells me there is something wrong I really have to have a look and
yes I'm building using all the warnings and checks on. I even have all the
GNAT style checks activated.

I don't want a language that let me do the same thing with hundredth ways among
which there is only one safe path. I'm not a gamer, fiddling with a piece of
code hours to find the good way is not what I'm looking for :)
So if you like to be as much constrained as possible, I think VB is much
better for this. Or even Logo. Plus it provides a turtle to help you.


You are really trying hard to fail to understand. All this is a trade off. We
all need lot of power (what VB or Logo won't give to us) but the power must be
*controlled* and it must come with a well defined *semantic*.

Pascal.

--

--|------------------------------------------------------
--| Pascal Obry Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--| http://www.obry.org
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595
Jul 23 '05 #752
REH wrote:
These will mostly fail on systems with alignment constraints (SPARC, PPC,
etc.).


Why?
--
Ioannis Vranos

http://www23.brinkster.com/noicys

[I am using 90 characters word-wrapping - (800/640) *72= 90 or better described as:
(800/640) *80 - 10 for quotation= 90. If someone finds it inconvenient, please let me know].
Jul 23 '05 #753
Pascal Obry wrote:
But you can propose a easy path that is safer. In this case there is lot of
more chance than the programmer will choose it. Easier is always appreciated :)
And a language must make it harder to do unsafe thing, like deallocation on
Ada. You have a instanciate Unchecked_Deallocation. The meaning is clear and
nobody can do that without noticing.

As Ludovic I appreciate a lot the help of the compiler and never try to fight
it. If it tells me there is something wrong I really have to have a look and
yes I'm building using all the warnings and checks on. I even have all the
GNAT style checks activated.

I don't want a language that let me do the same thing with hundredth ways among
which there is only one safe path. I'm not a gamer, fiddling with a piece of
code hours to find the good way is not what I'm looking for :)

So if you like to be as much constrained as possible, I think VB is much
better for this. Or even Logo. Plus it provides a turtle to help you.

You are really trying hard to fail to understand. All this is a trade off. We
all need lot of power (what VB or Logo won't give to us) but the power must be
*controlled* and it must come with a well defined *semantic*.

Actually most compilers provide warnings for lots of stuff and provide an option to
display all warnings (e.g. /Wall), even comparison between signed and unsigned integers
generates a warning. And they can also treat all warnings as *errors* if you specify so.

However the default is to display warnings for anything that is not required by the
standard to be treated as an error, and compile it.
In most cases, one fixes *all* warnings. However there *are* some cases where the
programmer knows better.

C++ is enabling by default, which I suppose is the opposite direction of Ada, and that's
why I think we can't understand one another. :-)
C++ being less restrictive as the default, doesn't mean a compiler does not generate lots
of warnings!

--
Ioannis Vranos

http://www23.brinkster.com/noicys

[I am using 90 characters word-wrapping - (800/640) *72= 90 or better described as:
(800/640) *80 - 10 for quotation= 90. If someone finds it inconvenient, please let me know].
Jul 23 '05 #754
Ioannis Vranos wrote:
Actually most compilers provide warnings for lots of stuff and provide
an option to display all warnings (e.g. /Wall), even comparison between
signed and unsigned integers generates a warning. And they can also
treat all warnings as *errors* if you specify so.

However the default is to display warnings for anything that is not
required by the standard to be treated as an error, and compile it.
In most cases, one fixes *all* warnings. However there *are* some cases
where the programmer knows better.

C++ is enabling by default, which I suppose is the opposite direction of
Ada, and that's why I think we can't understand one another. :-)
C++ being less restrictive as the default, doesn't mean a compiler does
not generate lots of warnings!

An example. First compile with the default behaviour, then with all warnings turned on:

int main()
{
int i=0;

unsigned j=4;

j<i;
}
C:\c>g++ temp.cpp -o temp.exe

C:\c>g++ -Wall temp.cpp -o temp.exe
temp.cpp: In function `int main()':
temp.cpp:7: warning: comparison between signed and unsigned integer expressions
temp.cpp:7: warning: statement has no effect

C:\c>


--
Ioannis Vranos

http://www23.brinkster.com/noicys

[I am using 90 characters word-wrapping - (800/640) *72= 90 or better described as:
(800/640) *80 - 10 for quotation= 90. If someone finds it inconvenient, please let me know].
Jul 23 '05 #755
REH

"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:1112026376.920221@athnrd02...
REH wrote:
These will mostly fail on systems with alignment constraints (SPARC, PPC, etc.).


Why?
--


Well, suppose your class contains a variable of type double, which on some
systems is 8 bytes and requires 8 byte alignment. The array you are
defining to hold the class is a character array, which only requires 1 byte
alignment. If it is created with a 1 byte alignment, when you create the
class in it using placement new, now the double is misaligned. When you
access it nasty things can happen. Intel processors can handled misaligned
variables, but take extra clock cycles to do so. On a SPARC or PowerPC, you
will throw a hardware exception (segmentation fault or machine check most
likely). A way around this problem is to either 1) make an array of
doubles, 2) union the array with a double, or 3) allocate from the heap.

REH
Jul 23 '05 #756
REH

"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:1112022773.497341@athnrd02...
In C++ you can always do:

#include <new>
class SomeClass
{
};
void somefunc()
{
unsigned char obj[sizeof(SomeClass)];

SomeClass *p= new(obj)SomeClass;

delete p;
}
as also:
#include <new>
class SomeClass
{
};
SomeClass *somefunc()
{
static unsigned char obj[sizeof(SomeClass)];

return new(obj)SomeClass;
}
int main()
{
SomeClass *p= somefunc();

delete p;
}
Here the object is created in the stack.

Another problem with this is you cannot use delete on a pointer returned
from placement new. You must instead call the destructor directly:
p->~SomeClass();

Jul 23 '05 #757
In article <d2*********@cui1.lmms.lmco.com>, "REH" <bo***@nowhere.net> writes:

"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:1112026376.920221@athnrd02...
REH wrote:
> These will mostly fail on systems with alignment constraints (SPARC, PPC, > etc.).


Why?
--


Well, suppose your class contains a variable of type double, which on some
systems is 8 bytes and requires 8 byte alignment. The array you are
defining to hold the class is a character array, which only requires 1 byte
alignment. If it is created with a 1 byte alignment, when you create the
class in it using placement new, now the double is misaligned. When you
access it nasty things can happen. Intel processors can handled misaligned
variables, but take extra clock cycles to do so. On a SPARC or PowerPC, you
will throw a hardware exception (segmentation fault or machine check most
likely). A way around this problem is to either 1) make an array of
doubles, 2) union the array with a double, or 3) allocate from the heap.


This can depend on the operating system.

On Alpha (and I presume on Itanium) VMS catches such exceptions and fixes
them up. It slows things down, but the result is still correct.
Jul 23 '05 #758
Ioannis Vranos <iv*@remove.this.grad.com> wrote:
Ioannis Vranos wrote:
Actually most compilers provide warnings for lots of stuff and provide
an option to display all warnings (e.g. /Wall), even comparison between
signed and unsigned integers generates a warning. And they can also
treat all warnings as *errors* if you specify so.

However the default is to display warnings for anything that is not
required by the standard to be treated as an error, and compile it.
In most cases, one fixes *all* warnings. However there *are* some cases
where the programmer knows better.

C++ is enabling by default, which I suppose is the opposite direction of
Ada, and that's why I think we can't understand one another. :-)
C++ being less restrictive as the default, doesn't mean a compiler does
not generate lots of warnings!

The question is not only about compiler warnings or errors. Ada (as a
language) has been designed so that it is possible for the
compiler to check many mistakes which may cause bad results at run time.
Ada also makes it easier for the user to notice this kind of errors.
For example:

procedure X is

type Metres is new Natural;
type Seconds is new Natural;

M : Metrses := 0;
S : Seconds := 10;
begin
if M < S then -- Error, < is not defined for these types
...
end if;
end X;

This is a bit more verbose than using pure int instead of Metres and
Seconds, but if I wanted a C++ compiler to check this kind of error, I'm
afread that the resulting C++ code would be much more verbose.

Such mistakes as using a pointer to nothing and writing past the array
bounds don't often happen in Ada.
An example. First compile with the default behaviour, then with all warnings tu
rned on:

int main()
{
int i=0;

unsigned j=4;

j<i;
}


procedure Temp is
I : Integer := 0;
J : Natural := 4;
begin
I < J;
end Temp;

Without any warnings:
# gnatmake temp
gcc -c temp.adb
temp.adb:5:05: missing ":="
gnatmake: "temp.adb" compilation error

Notice how the language prevents doing useless things.

If a replace I < J; with null; the result is:
gcc -c -gnatg temp.adb
temp.adb:2:04: warning: "I" is not modified, could be declared constant
temp.adb:2:04: warning: variable "I" is not referenced
temp.adb:3:04: warning: "J" is not modified, could be declared constant
temp.adb:3:04: warning: variable "J" is not referenced
gnatmake: "temp.adb" compilation error

--
Tapio
Jul 23 '05 #759
REH wrote:
Well, suppose your class contains a variable of type double, which on some
systems is 8 bytes and requires 8 byte alignment. The array you are
defining to hold the class is a character array, which only requires 1 byte
alignment. If it is created with a 1 byte alignment, when you create the
class in it using placement new, now the double is misaligned.

But we can treat a double variable as a sequence of unsigned chars/plain chars plus copy
it byte by byte (char/unsigned char) to a new unsigned char/char sequence and have an
exact working copy of the original. So since we can do this for stand alone
doubles/sequences of doubles, then why can't we do this in the double contained in a class
case?

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #760
REH wrote:
Another problem with this is you cannot use delete on a pointer returned
from placement new. You must instead call the destructor directly:
p->~SomeClass();

However in TC++PL 3, on page 576, there is a version of delete for placement new and
delete[] for placement new[]:
"void *operator new(size_t, void *p) throw() { return p; } // placement (10.4.11)
void operator delete(void *p, void *) throw() { }
void *operator new[](size_t, void *p) throw() { return p; }
void operator delete[](void *p, void *) throw() { }"

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #761
REH

"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:1112035652.831337@athnrd02...
REH wrote:
Another problem with this is you cannot use delete on a pointer returned
from placement new. You must instead call the destructor directly:
p->~SomeClass();

However in TC++PL 3, on page 576, there is a version of delete for

placement new and delete[] for placement new[]:
"void *operator new(size_t, void *p) throw() { return p; } // placement (10.4.11) void operator delete(void *p, void *) throw() { }
void *operator new[](size_t, void *p) throw() { return p; }
void operator delete[](void *p, void *) throw() { }"

OK, that's news to me. But how does the compiler know to call this version
of delete just from:

delete p;

?

Jul 23 '05 #762
REH

"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:1112034544.645999@athnrd02...
REH wrote:
Well, suppose your class contains a variable of type double, which on some systems is 8 bytes and requires 8 byte alignment. The array you are
defining to hold the class is a character array, which only requires 1 byte alignment. If it is created with a 1 byte alignment, when you create the class in it using placement new, now the double is misaligned.

But we can treat a double variable as a sequence of unsigned chars/plain

chars plus copy it byte by byte (char/unsigned char) to a new unsigned char/char sequence and have an exact working copy of the original. So since we can do this for stand alone doubles/sequences of doubles, then why can't we do this in the double contained in a class case?

I never said you couldn't. I was just pointing out that what you wrote was
not portable, and would not work for any arbitrary class. Besides, why
would you incur the extra time and complexity of manually moving the data
back and forth, byte-by-byte instead of just insuring the correct alignment
and letting the compiler take care of it?
Jul 23 '05 #763
REH wrote:
But we can treat a double variable as a sequence of unsigned chars/plain
chars plus copy
it byte by byte (char/unsigned char) to a new unsigned char/char sequence


and have an
exact working copy of the original. So since we can do this for stand


alone
doubles/sequences of doubles, then why can't we do this in the double


contained in a class
case?


I never said you couldn't.

What I meant, is that the above is a safe and portable operation to do. It is guaranteed
by the standard.

I was just pointing out that what you wrote was
not portable, and would not work for any arbitrary class. Besides, why
would you incur the extra time and complexity of manually moving the data
back and forth, byte-by-byte instead of just insuring the correct alignment
and letting the compiler take care of it?

This question can be rephrased to: "Why is memcpy() needed?".

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #764
REH wrote:
OK, that's news to me. But how does the compiler know to call this version
of delete just from:

delete p;

?

Forget what I said, it looks like I am wrong, and you are right:

http://www.parashift.com/c++-faq-lit...html#faq-11.10

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #765
Ioannis Vranos wrote:
REH wrote:
OK, that's news to me. But how does the compiler know to call this
version
of delete just from:

delete p;

?


Forget what I said, it looks like I am wrong, and you are right:

http://www.parashift.com/c++-faq-lit...html#faq-11.10

The default delete operators provided and accompany the default placement operators new,
perform no action.


--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #766
REH

"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:1112039976.169686@athnrd02...
I was just pointing out that what you wrote was
not portable, and would not work for any arbitrary class. Besides, why
would you incur the extra time and complexity of manually moving the data back and forth, byte-by-byte instead of just insuring the correct alignment and letting the compiler take care of it?

This question can be rephrased to: "Why is memcpy() needed?".

--

No, it is not about whether memcpy() is a necessary function. You purposely
over simplified what I did. I don't want to appear rude, but your whole
statement about moving a double byte-by-byte to avoid alignment issues is
just nonsense. You didn't take portability into account when you wrote the
snippets of code using placement new, and now you wish to backpedal. You
really are not going to convince me that you intended write all your classes
to copy all the bytes of variables with alignment needs greater than one,
instead of just fixing the alignment. Do you really expect my to believe
you would write:

struct foo {
foo(double d) : m_dbl(d) {}
double get() const
{
double tmp;
memcpy(&tmp, &m_dbl, sizeof(tmp));
return tmp;
}

private:
double m_dbl;
}

char buf[sizeof(foo)];

foo* pf = new(buf) foo();
double d = pf->get();
instead of:

struct foo {
foo(double d) : m_dbl(d) {}
double get() const {return m_dbl;}

private:
double m_dbl;
}

union data_type {
double align;
char buf[sizeof(foo)];
} data;

foo* pf = new(data.buf) foo();
double d = pf->get();
Jul 23 '05 #767
Hyman Rosen <hy*****@mail.com> writes:
Jerry Coffin wrote:
I see. So what is it that (you incorrectly believe) the C preprocessor
can do that a Lisp macro can't do?


Can Lisp macros manipulate the text of the macro arguments?


They don't manipulate text at all, but they _do_ manipulate the
_un_evaluated forms passed to them.

Here is a "top 5" list of why Lisp macros aren't anything like C
preprocessor stuff. At the bottom I give an example.

Top five reasons why Lisp macros are not similar to the C/C++
preprocessor in any meaningful sense.
Number 5:

The/a cpp is a, well, preprocessor. Typically a separate program
even. While you could dilute the meaning here to the point where a
compiler is a preprocessor for a linker is a processor for a loader is
a preprocessor for a cpu etc., the typical meaning is that such things
perform minor transformations on a block of input and had the result
to the primary processor.

Lisp macros are tightly bound up with both the definition of the total
language and any implmentation of it. Also expansion time is
interwoven with compilation, interpretation, or explicit evaluation.
They are available and can be defined during any phase: compile, load,
and execute/runtime.
Number 4:

The/a cpp is not Turing complete.

Lisp macros are Turing complete.
Number 3:

The/a cpp processes text, typically from a text stream such as (most
typically) a text file.

Lisp macros process _data structures_. In particular the syntax trees
output from the parser. Text is long gone before macros are involved
at all.
Number 2:

The/a cpp doesn't know or have any access to the full language, user
defined functions, or its environment.

Lisp macros are just Lisp functions which can make use of the entire
language, and any other user defined functions and macros in libraries
or the running image. They also have access to their lexical
environment information (such as type and profile information) as well
as any public aspects of the global system/application.
And the Number 1 reason why Lisp macros are not similar to the C/C++
preprocessor in any meaningful sense:

Jerry Coffin thinks they are.
;-) and just to make sure :-) :-)
-----------------------------

The astute reader will have noticed that it is C++ _templates_ which
are slighly similar to Lisp macros. And they would be right.
Templates are significantly less expressive and mind numbingly painful
to use in comparison, but they are Turing complete and you can do some
interesting things with them.

For example, while it might take several pages of code, I think it is
_physically_ possible (i.e., humanly doable not just theoretically
doable) to achieve the (somewhat contrived) following example with
templates. Note: I don't see how you can do this _in_ Ada at all.
Allow a user/programmer to define a dictionary like object while
ensuring at compile time that the size of the table implementing it is
a prime number.

(defun small-primep (n)
(and (< 0 n most-positive-fixnum)
(the-primes :from n :to n)))
(deftype prime () `(and integer (satisfies small-primep)))
(defmacro define-dictionary
((name &key (size 101) (test #'eql) (hash #'sxhash)) &body body)
(assert (symbolp name) nil
"Dictionary names must be symbols. ~A is of type ~A"
name (type-of name))
(assert (typep size 'prime) nil
(prime-failure-message size name))
`(defvar ,name
,(if body
`(let ((it (make-hash-table
:test ,test :size ,size :hash-function ,hash)))
,@(mapcar #'(lambda (p)
`(setf (gethash ,(car p) it) ,(cdr p)))
body)
it)
`(make-hash-table
:test ,test :size ,size :hash-function ,hash))))
(defun prime-failure-message (n name)
(concatenate
'string
(format nil "Dictionary ~A: " name)
(cond
((not (integerp n))
(format nil "~A of type ~A is not a number" n (type-of n)))
((< n 0)
(format nil "~A < 0; Dictionary sizes must > 0 and prime numbers" n))
((> n most-positive-fixnum)
(format nil "Dictionary sizes must be prime numbers < ~A"
most-positive-fixnum))
(t
(format nil "~A is not prime; Next prime larger than ~A is ~A"
n n (first (the-primes :from n :to (+ 1000 n))))))))
At _compile_ time

(define-dictionary (foo :size 20))

produces:

Error: Dictionary FOO: 20 is not prime; Next prime larger than 20 is 23
(define-dictionary (foo :size 23)
(1 . "one")
(2 . "two")
(3 . "three"))

Compiles, passes checks and produces the dictionary with the given entries.
This generates the following code:

(DEFVAR FOO
(LET ((IT (MAKE-HASH-TABLE
:TEST #<Function EQL>
:SIZE 23
:HASH-FUNCTION #<Function SXHASH>)))
(SETF (GETHASH 1 IT) "one")
(SETF (GETHASH 2 IT) "two")
(SETF (GETHASH 3 IT) "three")
IT))
/Jon

--
'j' - a n t h o n y at romeo/charley/november com
Jul 23 '05 #768
REH wrote:
No, it is not about whether memcpy() is a necessary function. You purposely
over simplified what I did. I don't want to appear rude, but your whole
statement about moving a double byte-by-byte to avoid alignment issues is
just nonsense.

My point was that we can create objects in a low level way like that.
You didn't take portability into account when you wrote the
snippets of code using placement new, and now you wish to backpedal.

I considered them to be portable (apart from the non-explicit call of destructors mistake).
You
really are not going to convince me that you intended write all your classes
to copy all the bytes of variables with alignment needs greater than one,
instead of just fixing the alignment.

Do you really expect my to believe
you would write:

struct foo {
foo(double d) : m_dbl(d) {}
double get() const
{
double tmp;
memcpy(&tmp, &m_dbl, sizeof(tmp));
return tmp;
}

private:
double m_dbl;
}

char buf[sizeof(foo)];

foo* pf = new(buf) foo();
double d = pf->get();
instead of:

struct foo {
foo(double d) : m_dbl(d) {}
double get() const {return m_dbl;}

private:
double m_dbl;
}

union data_type {
double align;
char buf[sizeof(foo)];
} data;

foo* pf = new(data.buf) foo();
double d = pf->get();


Yes the first one is also always guaranteed to work. In summary, the standard guarantees
that you can read *any* POD type as a sequence of chars/unsigned chars and copy them to a
new char/unsigned char array and you will have an exact, working copy of the original
*POD* type.

For non-POD types, you can only read them as sequences of unsigned chars only, but if you
copy them it is *not* guaranteed that you will have either exact or working copies of the
original.

No alignment is mentioned about this anywhere.
Now this means, that strictly speaking my code with the class having the defined
constructor and destructor is not portable since is a non-POD type, and thus should not
had used it in clc++, since strict theoretical portability is important in here.
However the following code *is* portable:
#include <iostream>
#include <cstring>

class SomeClass
{
public:

double d;
int i;
float f;
long l;
};
int main()
{
using namespace std;

unsigned char array[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

memcpy(array, &obj, sizeof(obj));

SomeClass *p= reinterpret_cast<SomeClass *>(array);

cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";
}
C:\c>temp
1 2 3 4

C:\c>
So since this is *guaranteed* to be portable, why this isn't?
#include <iostream>
#include <cstring>

class SomeClass
{
public:

double d;
int i;
float f;
long l;
};
int main()
{
using namespace std;

unsigned char array[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

SomeClass *p= new(array)SomeClass(obj);

cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";
}
C:\c>temp
1 2 3 4

C:\c>
--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #769
"Paul Mensonides" <le******@comcast.net> writes:
Hyman Rosen wrote:
Jerry Coffin wrote:
I see. So what is it that (you incorrectly believe) the C
preprocessor can do that a Lisp macro can't do?
Can Lisp macros manipulate the text of the macro arguments?


You use _reader_ macros for that sort of thing.

Lisp macros cannot produce partial syntax either, whereas C/C++
macros can (e.g. on macro can create a '{' and another separate
invocation can create the closing '}').
Again, that would be the sort of thing you would use reader macros.
It's worth noting again that Lisp macros (the kind you generally mean
when unqualified) do not work on text, they work on the syntax trees
passed to them.

Jerry is correct to say that they do similar things--they parametize
code with code.
But that is not really what they do. It is _one_ thing you can _use_
them to do.

The main differences is that in Lisp (etc.) their


I think the main differences are the ones I listed.
/Jon

--
'j' - a n t h o n y at romeo/charley/november com
Jul 23 '05 #770
Tapio Kelloniemi writes:
If a replace I < J; with null; the result is:
gcc -c -gnatg temp.adb
temp.adb:2:04: warning: "I" is not modified, could be declared constant
temp.adb:2:04: warning: variable "I" is not referenced
temp.adb:3:04: warning: "J" is not modified, could be declared constant
temp.adb:3:04: warning: variable "J" is not referenced
gnatmake: "temp.adb" compilation error


This is an excellent example of the power of GNAT. I think this would
deserve more publicity in future presentations of the language and of
GNAT.

--
Ludovic Brenta.

Jul 23 '05 #771
REH

"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:1112045099.679682@athnrd02...
However the following code *is* portable:
#include <iostream>
#include <cstring>

class SomeClass
{
public:

double d;
int i;
float f;
long l;
};
int main()
{
using namespace std;

unsigned char array[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

memcpy(array, &obj, sizeof(obj));

SomeClass *p= reinterpret_cast<SomeClass *>(array);

cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";
}
C:\c>temp
1 2 3 4

C:\c>
So since this is *guaranteed* to be portable, why this isn't?
#include <iostream>
#include <cstring>

class SomeClass
{
public:

double d;
int i;
float f;
long l;
};
int main()
{
using namespace std;

unsigned char array[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

SomeClass *p= new(array)SomeClass(obj);

cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";
}
C:\c>temp
1 2 3 4

C:\c>
--
Ioannis Vranos

No, NEITHER is portable! That both have alignment issues! Both exihibit
undefined behavior. Show me where in the standard is says you may cast a
pointer to a char array to a pointer of any other type (other than another
signed/unsigned char*) and access it. You do this on a system that cannot
handle misaligned accesses, and your program will most likely crash!

Jul 23 '05 #772
"Ludovic Brenta" <lu************@insalien.org> wrote in message
news:87***************@insalien.org...
....
The C++ way of catching all exceptions of a class and its derived
classes can lead to confusion. One can have multiple exception
handlers for the same exception and it may not be immediately obvious
to the reader which one is called. I see this as a maintenance
problem.


If Ada had some sort of exception classes, there certainly would be a
overlapping handler check. Having two different handlers for any possible
exeception would be prohibited (it certainly is now). So I don't find this
much a reason for not having this capability. The reasons for not having it
are finalization, memory allocation, and compatibility with Ada 83 & Ada 95.
(And mainly that the person working on it ran out of energy for it, and no
one else picked it up.)

Randy.

Jul 23 '05 #773
Jerry Coffin wrote:
And so? What part of "it seems likely" don't you understand?
I was commenting that the slides you quoted were irrelevant to your
comment
It seems likely to me that if
they were using Ada for the hand-written code, they'd generate Ada
as well.


I would appreciate if did resort to begging the question when
responding.

Jul 23 '05 #774
Jerry Coffin wrote:
If I ever teach a class,
If you teach a class the way you argue in newsgroups, your students
would not approve. You would frustrate them because you would be
putting words in their mouth and insulting them instead of listening to
what they are saying, and you would be ignoring arguments that show you
are error instead of admitting error and going back to find the truth.
anybody who tries to abuse Turing completeness like this


I haven't abused the definition of Turing completeness. I was making
as comment how your statement
You clearly don't understand even the simplest logic. Being able to
do all the same things directly implies having similar capabilities.

didn't address what Jayessay was talking about.

Jul 23 '05 #775
REH wrote:
#include <iostream>
#include <cstring>

class SomeClass
{
public:

double d;
int i;
float f;
long l;
};
int main()
{
using namespace std;

unsigned char array[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

memcpy(array, &obj, sizeof(obj));

SomeClass *p= reinterpret_cast<SomeClass *>(array);

cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";
}
C:\c>temp
1 2 3 4

C:\c>
So since this is *guaranteed* to be portable, why this isn't?
#include <iostream>
#include <cstring>

class SomeClass
{
public:

double d;
int i;
float f;
long l;
};
int main()
{
using namespace std;

unsigned char array[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

SomeClass *p= new(array)SomeClass(obj);

cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";
}
C:\c>temp
1 2 3 4

C:\c>
--
Ioannis Vranos


No, NEITHER is portable! That both have alignment issues! Both exihibit
undefined behavior. Show me where in the standard is says you may cast a
pointer to a char array to a pointer of any other type (other than another
signed/unsigned char*) and access it. You do this on a system that cannot
handle misaligned accesses, and your program will most likely crash!


Perhaps you are right. If you have the standard, have a look at 3.9-2, 3.9-4, and 3.9-5
which I think agrees with you.

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #776
Hyman Rosen wrote:
Martin Krischik wrote:
Disclaimer: Both sources might not be in working order - everytime I
switch compiler (IBM C++ -> MS-C++ -> G++) the code need reworking and
the switch to GNU is not finished yet.
I looked at Ada Array and immediately found errors
(eg., in 'typename TheIndex const First;' the 'typename'
keyword is not permitted).
I know the code is full of problem zones and I think I fixed that in
"Ada::Range" allready. The sad thing is that it did compile with one
compiler and it won't with the next.

The last fix I did was "throw ( ... )" - IBM accepts it. MS even warns you
about missing features if you try anthing else.

The GNU compiler immediately moaned about it. I checked the ISO standard and
hey "throw ( ... )" isn't part of the ISO standart. You never stop
learning!

So I changed to "throw ( std::exeption )" knowing that this will result in
warnings in MS-C++ (and splint and pc-lint for that matter).
I suggest you try out your
code on Comeau, God's Own C++ Compiler (they ought to
trademark that phrase :-) It's available on the web at
<http://www.comeaucomputing.com/tryitout/>.


I try that after I got a working GNU version.

Martin
--
mailto://kr******@users.sourceforge.net
Ada programming at: http://ada.krischik.com

Jul 23 '05 #777
* Martin Krischik:

The last fix I did was "throw ( ... )" - IBM accepts it. MS even warns you
about missing features if you try anthing else.
"throw (...)" is not standard C++ syntax.

The GNU compiler immediately moaned about it. I checked the ISO standard and
hey "throw ( ... )" isn't part of the ISO standart. You never stop
learning!

So I changed to "throw ( std::exeption )" knowing that this will result in
warnings in MS-C++ (and splint and pc-lint for that matter).


Why not "throw std::exception();", or, if you're rethrowing, "throw;".

Btw., could you Ada folks please stop spouting new disconnected threads or
else at least indicate wherever the hell your postings originated, perhaps
also with a note mentioning the crossposting.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #778
Ludovic Brenta a écrit :
Pascal Obry once made an interesting remark: what is important for the
safety of a language is not what it allows but what it forbids.

Actually, I think he borrowed it from my "pensees" web page (sorry, it
is in French) at http://www.adalog.fr/publicat/pensees.htm)
--
---------------------------------------------------------
J-P. Rosen (ro***@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr
Jul 23 '05 #779
Pascal Obry wrote:
Ioannis Vranos <iv*@remove.this.grad.com> writes:

Now may you explain how the ability to use negative subranges for built in
array indices makes Ada better for any domain problem?

For a domain problem where you have to create an area centered on (0,0)
for example. What about a vector representing altitude, the sub-zero values
being under the water. Just some examples, I bet you'll be able to think about
lot more :)


One classical example is solving the eight queens problem. There's an
elegant solution using arrays with ranges starting at several values.
Jul 23 '05 #780
jayessay wrote:
Hyman Rosen <hy*****@mail.com> writes:
Jerry Coffin wrote:
I see. So what is it that (you incorrectly believe) the C
preprocessor can do that a Lisp macro can't do?
Can Lisp macros manipulate the text of the macro arguments?


They don't manipulate text at all, but they _do_ manipulate the
_un_evaluated forms passed to them.

Here is a "top 5" list of why Lisp macros aren't anything like C
preprocessor stuff. At the bottom I give an example.


Nobody said that the mechanisms are equivalent. Lisp macros are like C/C++
macros in a pretty major way: they parametize code with code.
Number 5:

The/a cpp is a, well, preprocessor. Typically a separate program
even. While you could dilute the meaning here to the point where a
compiler is a preprocessor for a linker is a processor for a loader is
a preprocessor for a cpu etc., the typical meaning is that such things
perform minor transformations on a block of input and had the result
to the primary processor.

Lisp macros are tightly bound up with both the definition of the total
language and any implmentation of it. Also expansion time is
interwoven with compilation, interpretation, or explicit evaluation.
They are available and can be defined during any phase: compile, load,
and execute/runtime.
So what? Where and when they can be evaluated doesn't mean that the mechanisms
are totally dissimilar.
Number 4:

The/a cpp is not Turing complete.
Yes it is.
Number 3:

The/a cpp processes text, typically from a text stream such as (most
typically) a text file.
No, a C or C++ preprocessor processes tokens, not text.
Lisp macros process _data structures_. In particular the syntax trees
output from the parser. Text is long gone before macros are involved
at all.
So what? A syntax tree is code, as is source code text.
Number 2:

The/a cpp doesn't know or have any access to the full language, user
defined functions, or its environment.
So what? This is the same thing as your fifth reason. When or where it can be
evaluated doesn't change what it does.
Lisp macros are just Lisp functions which can make use of the entire
language, and any other user defined functions and macros in libraries
or the running image. They also have access to their lexical
environment information (such as type and profile information) as well
as any public aspects of the global system/application.
Again, so what? There is no doubt that Lisp macros are superior to C/C++ macros
in most categories. However, that doesn't change what they fundamentally do:
parametize code with code.
-----------------------------

The astute reader will have noticed that it is C++ _templates_ which
are slighly similar to Lisp macros. And they would be right.
Templates are significantly less expressive and mind numbingly painful
to use in comparison, but they are Turing complete and you can do some
interesting things with them.


C++ templates are similar to Lisp macros also, but C/C++ macros are much closer.
The template mechanism parametizes code with types (primarily) and only
indirectly parametizes code with code.

To reiterate: nobody has said that C/C++ macros are as powerful as Lisp or
Scheme macros. However, despite everything you say, Lisp and Scheme macros
parametize code with code--regardless of when or where that can happen. That is
the same capability that C/C++ macros have. Does Lisp do it better? Yes. Does
Scheme do it better still? Yes. Neither of those answers precludes the
similarity in what the mechanisms do, nor do any of your reasons.

Regards,
Paul Mensonides
Jul 23 '05 #781
jayessay wrote:
"Paul Mensonides" <le******@comcast.net> writes:

Lisp macros cannot produce partial syntax either, whereas C/C++
macros can (e.g. on macro can create a '{' and another separate
invocation can create the closing '}').


Again, that would be the sort of thing you would use reader macros.
It's worth noting again that Lisp macros (the kind you generally mean
when unqualified) do not work on text, they work on the syntax trees
passed to them.


Neither do macros in C or C++. They operate on tokens. In any case, the
difference is meaningless. The only thing that matters is what the semantics
are (such as name binding). Lisp macros are easily inferior to Scheme macros in
that sense.
Jerry is correct to say that they do similar things--they parametize
code with code.


But that is not really what they do. It is _one_ thing you can _use_
them to do.


That is exactly what they do. It is irrelevant whether that code is in the form
of a syntax tree or not. The kind of thing that you seem to be referring to is
what Haskell does instead.
The main differences is that in Lisp (etc.) their


I think the main differences are the ones I listed.


Obviously.

Regards,
Paul Mensonides
Jul 23 '05 #782
* Ludovic Brenta:
int main() try


^
Isn't there a missing { here?


No, although this particular syntax is usually used for constructors
only.
Jul 23 '05 #783
Alf P. Steinbach wrote:
* Martin Krischik:

The last fix I did was "throw ( ... )" - IBM accepts it. MS even warns
you about missing features if you try anthing else.
"throw (...)" is not standard C++ syntax.


I did say that a few lines later. It's actually down there is the quote:
The GNU compiler immediately moaned about it. I checked the ISO standard
and hey "throw ( ... )" isn't part of the ISO standart. You never stop
learning!

So I changed to "throw ( std::exeption )" knowing that this will result
in warnings in MS-C++ (and splint and pc-lint for that matter).


Why not "throw std::exception();", or, if you're rethrowing, "throw;".


You missunderstood. I speak about:

void f ()
throw (std::exception)
{
....
}

as stated in ISO/IEC14882(15.4). I know it's one of the C++ features which
are seldomly used and using it is an uphill struggle - just like using
const was when it first appeared. But that never stops me.

With Regards

Martin

--
mailto://kr******@users.sourceforge.net
Ada programming at: http://ada.krischik.com

Jul 23 '05 #784
Ioannis Vranos wrote:
int main()
{
using namespace std;

unsigned char array[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

SomeClass *p= new(array)SomeClass(obj);

cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";
}
C:\c>temp
1 2 3 4

C:\c>
--
Ioannis Vranos


No, NEITHER is portable! That both have alignment issues! Both exihibit
undefined behavior. Show me where in the standard is says you may cast a
pointer to a char array to a pointer of any other type (other than
another
signed/unsigned char*) and access it. You do this on a system that
cannot
handle misaligned accesses, and your program will most likely crash!



Perhaps you are right. If you have the standard, have a look at 3.9-2,
3.9-4, and 3.9-5 which I think agrees with you.


I couldn't find anything that guarantees the alignment of an unsigned char
array like that. I don't think there is such a guarantee. But I do know that
according to 3.7.3.1.2 of the Standard, a pointer returned from operator new
is properly aligned for any type. Also I think somewhere it guarantees copying
to and back from an unsigned char array is guaranteed to be portable (if the
array is large enough). I couldn't find that reference though.
Jul 23 '05 #785
"Paul Mensonides" <le******@comcast.net> writes:
Nobody said that the mechanisms are equivalent. Lisp macros are like C/C++
macros in a pretty major way: they parametize code with code.
No, they are fundamentally code _transformers_, not parametric
substituters.

Lisp macros are tightly bound up with both the definition of the total
language and any implmentation of it. Also expansion time is
interwoven with compilation, interpretation, or explicit evaluation.
They are available and can be defined during any phase: compile, load,
and execute/runtime.


So what? Where and when they can be evaluated doesn't mean that the
mechanisms are totally dissimilar.


OK, you would then also claim that the preprocessor is basically
similar to the C++ compiler. Fine. I think that makes the term
basically meaningless.

The/a cpp is not Turing complete.


Yes it is.


No, it is not. The only way to get it to act as such is to run it in
phases over its own output.

The/a cpp processes text, typically from a text stream such as (most
typically) a text file.


No, a C or C++ preprocessor processes tokens, not text.


No, the _input_ is _text_. Of course it turns that into _tokens_ but
that is _irrelevant_

Lisp macros process _data structures_. In particular the syntax trees
output from the parser. Text is long gone before macros are involved
at all.


So what? A syntax tree is code, as is source code text.


You can't be serious. OK, so the source code of a C++ program is the
same as the AST produced by the frontend. You have again rendered the
term "syntax tree" basically meaningless.

The/a cpp doesn't know or have any access to the full language, user
defined functions, or its environment.


So what? This is the same thing as your fifth reason. When or
where it can be evaluated doesn't change what it does.


No it is not the same, and it is telling that you think it is. And it
makes a huge difference. You can write programs with Lisp macros
pretty much like you write any other program. You write them _in_ the
language, not as some adjunct separate aspect to the language. That
level of expressivity and use of previously defined libraries of
functions is as important as being able to use class libraries and
language intrincs in typical programs. I don't see how you can
plausibly disagree with this.
Lisp macros are just Lisp functions which can make use of the entire
language, and any other user defined functions and macros in libraries
or the running image. They also have access to their lexical
environment information (such as type and profile information) as well
as any public aspects of the global system/application.


Again, so what?


See above. To claim that this is a "so what" is to claim that there
is no need or anything particularly useful about being able to use any
language construct and/or library in programming any program. I
suppose you don't realize that that is what you are actually saying
here, because I can't believe you would actually think this.

There is no doubt that Lisp macros are superior to C/C++ macros in
most categories. However, that doesn't change what they
fundamentally do: parametize code with code.
I'm afraid that saying its so doesn't make it so. They are code
transformers. Of couse you can use them to "parameterize" code, but
that is a single _use_ case.

The astute reader will have noticed that it is C++ _templates_ which
are slighly similar to Lisp macros. And they would be right.
Templates are significantly less expressive and mind numbingly painful
to use in comparison, but they are Turing complete and you can do some
interesting things with them.


C++ templates are similar to Lisp macros also, but C/C++ macros are
much closer.


Not in their more fundamental character. Templates are about
metaprogramming - not very potent example, but metaprogramming
nonetheless. Lisp macros are still _the_ most capable extent example
of metaprogramming.
The template mechanism parametizes code with types (primarily) and
only indirectly parametizes code with code.
That's pretty irrelevant.

To reiterate: nobody has said that C/C++ macros are as powerful as
Lisp or Scheme macros. However, despite everything you say, Lisp
and Scheme macros parametize code with code
And to reiterate, that is not what they primarily do.

better still? Yes. Neither of those answers precludes the
similarity in what the mechanisms do, nor do any of your reasons.


That basically eliminates any meaning in most of the terms:
"preprocessor", "compiler", "metaprogramming", "code transformer".
Fine. But I think that's pretty extreme thing to do simply to try to
pretend that C/C++ macros are anything like Lisp macros.
/Jon

--
'j' - a n t h o n y at romeo/charley/november com
Jul 23 '05 #786
"Paul Mensonides" <le******@comcast.net> writes:
jayessay wrote:
"Paul Mensonides" <le******@comcast.net> writes:
Lisp macros cannot produce partial syntax either, whereas C/C++
macros can (e.g. on macro can create a '{' and another separate
invocation can create the closing '}').


Again, that would be the sort of thing you would use reader macros.
It's worth noting again that Lisp macros (the kind you generally mean
when unqualified) do not work on text, they work on the syntax trees
passed to them.


Neither do macros in C or C++. They operate on tokens. In any
case, the difference is meaningless.


Actually the difference is very important.

The only thing that matters is what the semantics are
Indeed.

(such as name binding). Lisp macros are easily inferior to Scheme
macros in that sense.
No, they are a proper superset of Scheme macros. The hygiene issue
is largely irrelevant due to CL being a lisp2 (while Scheme is a
lisp1).

Jerry is correct to say that they do similar things--they parametize
code with code.


But that is not really what they do. It is _one_ thing you can _use_
them to do.


That is exactly what they do.


No, but I don't think you will understand this anytime soon. Let me
ask you here, just _why_ do you think this? Maybe more to the point,
what do you think "parameterization" means here? It may be that we
are just not on the same page with the term definitions.

in the form of a syntax tree or not. The kind of thing that you
seem to be referring to is what Haskell does instead.


No, plain Haskell has no facility for this, but there are macro
systems that have been placed on it to provide some of the capability.

The main differences is that in Lisp (etc.) their


I think the main differences are the ones I listed.


Obviously.


;-)
/Jon

--
'j' - a n t h o n y at romeo/charley/november com
Jul 23 '05 #787

Jean-Pierre Rosen <ro***@adalog.fr> writes:
Actually, I think he borrowed it from my "pensees" web page (sorry, it is in
French) at http://www.adalog.fr/publicat/pensees.htm)


No I think I read that in your book about Ada (don't have the name handy).

Pascal.

--

--|------------------------------------------------------
--| Pascal Obry Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--| http://www.obry.org
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595
Jul 23 '05 #788
Jerry Coffin wrote:
The point is that picking the language for that 70% seems to
take one choice in one list box -- i.e. the most utterly trivial amountof work possible.
What are you trying to say with this sentence? It seems devoid of any
relavent information or meaning.
are you honestly suggesting that
it's particularly likely that they'd choose to generate C if they were
planning to write the remainder in Ada?
Now I don't have to be pigeon holed into only that suggestion. There
are more reasonable suggestions. For instance, they could be reusing
libraries written in Ada for maybe 10% of the remaining code. Another
15% could use this libraries and thus be written in Ada.
I don't recall anybody here having suggested that SCADE is the be-all
and end-all of format tools.
I never said you did. I was assuming that SCADE is a decent formal
tool which implies that they use SCADE to generate a most complete
subsystem that represented about 70% of the code base.
I drew exactly two conclusions: 1) that 100% minus 70% leaves 30%, and
2) that these _seem_ to be sufficiently large projects that 30% of themstill constitutes a substantial amount of code.
Exactly two huh? What about
It seems likely to me that if
they were using Ada for the hand-written code, they'd generate Ada
as well.
That looks like a conclusion to me. That sentence that you are
misquoting applies to all you conclusions and implicit implications.
Furthermore, if are calling
100% minus 70% leaves 30%
a conclusion as oppose to an assertion. One should expect that it was
preceeded by an arguement or proof of some sort. Being that you didn't
provide either, this "conclusion" is either a) actually an assertion
and disqualified to be member of your "exactly two conclusions" or b) a
conclusion that you jumped to by not providing an arguement to support
it.

And just for kicks
please expound on your form of math in which 100 minus 70 doesn't

equal 30.

when the numbers are in base 8 of course ;-)

Jul 23 '05 #789
Jerry Coffin wrote:
First of all, at least in my dictionary, "indicate" is defined with
words like "points to" and "suggests", NOT "proves" or anything very
similar.
Really?

http://dictionary.reference.com/search?q=indicates
entry four
"To state or express briefly (e.g. indicated his wishes in a letter;
indicating her approval with a nod.)"

seems to provide the most appropriate definition, which just happens to
support my statement. You should also note that the "points to" and
"suggests" entries have other very important words next to them which
render them as inappropriate to use for the meaning of the word
"indicate" in this dialog.
Second, I have to wonder whether you really have a good idea of the
size of project we're talking about.
Yes, I have a decent idea as to the size of the project. However, this
is irrelevent.
Second, unless porting Ada compilers is a LOT more expensive than
porting C++ compilers <and so on>

I thought we were talking about C compilers. Anyway my point is that
is that if SCADE already generates C code and the subsystem that they
are targetting with SCADE has a C compiler. Why should they commision
an Ada compiler so that they could generate Ada code only to compile it
back to machine code when the C compiler will generate the machine
code? C (in the can of SCADE) is the intermediate language because it
has the available compilers for the targetted platform.
I'll openly admit that the slides don't absolutely _prove_ nearly as
much as we'd like to know.
Wow! I am impressed by the extent of you admission. We have made real
progress here in your admission of the trivial.
They're generally vague, lacking detail,
definition or rigor -- but despite that they still constitute roughly
95% of the hard evidence presented so far in this entire thread!


I submit this paperweight as hard evidence. I am not sure as to what
it is evidence of, but I know it is hard. That was demonstrates when I
dropped it on my foot ;-) So now this paperweight makes up 25% percent
of the evidence.

I am curious how these three presentations can make of 95% of
something. 75% I can see but 95%?

Jul 23 '05 #790
Pascal Obry a écrit :
Jean-Pierre Rosen <ro***@adalog.fr> writes:

Actually, I think he borrowed it from my "pensees" web page (sorry, it is in
French) at http://www.adalog.fr/publicat/pensees.htm)

No I think I read that in your book about Ada (don't have the name handy).

Yes, it is in both... I just took the opportunity for a shameless plug :-)

--
---------------------------------------------------------
J-P. Rosen (ro***@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr
Jul 23 '05 #791

"Tapio Kelloniemi" <sp****@thack.org> skrev i en meddelelse
news:IQ*****************@reader1.news.jippii.net.. .
Ioannis Vranos <iv*@remove.this.grad.com> wrote:
Ioannis Vranos wrote:
Actually most compilers provide warnings for lots of stuff and provide
an option to display all warnings (e.g. /Wall), even comparison between
signed and unsigned integers generates a warning. And they can also
treat all warnings as *errors* if you specify so.

However the default is to display warnings for anything that is not
required by the standard to be treated as an error, and compile it.
In most cases, one fixes *all* warnings. However there *are* some cases
where the programmer knows better.

C++ is enabling by default, which I suppose is the opposite direction of
Ada, and that's why I think we can't understand one another. :-)
C++ being less restrictive as the default, doesn't mean a compiler does
not generate lots of warnings!

The question is not only about compiler warnings or errors. Ada (as a
language) has been designed so that it is possible for the
compiler to check many mistakes which may cause bad results at run time.
Ada also makes it easier for the user to notice this kind of errors.
For example:

procedure X is

type Metres is new Natural;
type Seconds is new Natural;

M : Metrses := 0;
S : Seconds := 10;
begin
if M < S then -- Error, < is not defined for these types


But now you have problems calculating the velocity, right?

type Velocity is new Natural;
V: Velocity = M/S; // probably a compiler error. ...
end if;
end X;

This is a bit more verbose than using pure int instead of Metres and
Seconds, but if I wanted a C++ compiler to check this kind of error, I'm
afread that the resulting C++ code would be much more verbose.
Not so. There is an excellent library which does exactly what you want -
using templates, of course.
Such mistakes as using a pointer to nothing and writing past the array
bounds don't often happen in Ada. What makes you believe they happen regularly in C++?
An example. First compile with the default behaviour, then with all
warnings tu
rned on:

int main()
{
int i=0;

unsigned j=4;

j<i;
}
procedure Temp is
I : Integer := 0;
J : Natural := 4;
begin
I < J;
end Temp;

Without any warnings:
# gnatmake temp
gcc -c temp.adb
temp.adb:5:05: missing ":="
gnatmake: "temp.adb" compilation error

Notice how the language prevents doing useless things.

If a replace I < J; with null; the result is:
gcc -c -gnatg temp.adb
temp.adb:2:04: warning: "I" is not modified, could be declared constant
temp.adb:2:04: warning: variable "I" is not referenced
temp.adb:3:04: warning: "J" is not modified, could be declared constant
temp.adb:3:04: warning: variable "J" is not referenced
gnatmake: "temp.adb" compilation error


I see no real difference here between a good-quality C++ compiler and Ada.
--
Tapio


/Peter
Jul 23 '05 #792
"Peter Koch Larsen" <pk*****@mailme.dk> wrote:
"Tapio Kelloniemi" <sp****@thack.org> skrev i en meddelelse
news:IQ*****************@reader1.news.jippii.net. ..
The question is not only about compiler warnings or errors. Ada (as a
language) has been designed so that it is possible for the
compiler to check many mistakes which may cause bad results at run time.
Ada also makes it easier for the user to notice this kind of errors.
For example:

procedure X is

type Metres is new Natural;
type Seconds is new Natural;

M : Metrses := 0;
S : Seconds := 10;
begin
if M < S then -- Error, < is not defined for these types


But now you have problems calculating the velocity, right?

type Velocity is new Natural;
V: Velocity = M/S; // probably a compiler error.

Yes, but I can tell the compiler that I know better:
V : Velocity := Velocity (Integer (M) / Integer (S));

Also other readers of my code now know surely that this is what I meant.
This is a bit more verbose than using pure int instead of Metres and
Seconds, but if I wanted a C++ compiler to check this kind of error, I'm
afread that the resulting C++ code would be much more verbose.


Not so. There is an excellent library which does exactly what you want -
using templates, of course.


That is a good thing. If all C++ programmers used it, I think their
programs would benefit a lot of it.
Such mistakes as using a pointer to nothing and writing past the array
bounds don't often happen in Ada.

What makes you believe they happen regularly in C++?


They just happen. Why people had otherwise created such tools as valgrind
(http://valgrind.kde.org/). I also use it myself for Ada to eliminate memory
leaks. Writing past array bounds unintentionally is quite easy. In Ada
Constraint_Error is raised, but C++ program segfaults. Or even worse, it
does not segfault immediately, but when the function is exited (as the
return address has been destroyed). STL is safer, but it cannot always be
used (eg. when interfacing to foreign code).
An example. First compile with the default behaviour, then with all
warnings tu
rned on:
[--] If a replace I < J; with null; the result is:
gcc -c -gnatg temp.adb
temp.adb:2:04: warning: "I" is not modified, could be declared constant
temp.adb:2:04: warning: variable "I" is not referenced
temp.adb:3:04: warning: "J" is not modified, could be declared constant
temp.adb:3:04: warning: variable "J" is not referenced
gnatmake: "temp.adb" compilation error


I see no real difference here between a good-quality C++ compiler and Ada.


Another example:

int* f()
{
int i = 3;
int& l = *(new int);

l = i;
int* p = &i; // Should be int* p = &l;

return p;
}

int main()
{
int* p = f();
*p = 4;
return 0;
}

# g++ -Wall -o temp temp.cc
#

Not even a warning and the program does not crash on my system! Valgrind
revealed the error (and thought it was a G++ bug).
If the code above is modified a bit, even the best compiler cannot
know for sure that we are doing evil things.

The same in Ada:

procedure Temp is
type Int_Ptr is access Integer;

function F return Int_Ptr is
I : Integer := 3;
L : Int_Ptr := new Integer;
P : Int_Ptr;
begin
L.all := I;
P := I'Access; -- Should be P := L;
return P;
end F;

A : Int_Ptr;
begin
A := F;
A.all := 4;
end Temp;

# gcc -c -gnatg temp.adb
temp.adb:5:04: (style): subprogram body has no previous spec
temp.adb:11:12: prefix of "Access" attribute must be aliased

So if I really want to pass a pointer to a local to the caller, I should
change
I : Integer := 3;
to
I : aliased Integer := 3;

Also note that the lines which were "mistyped" are much closer to each
other in C++ than in Ada.

--
Tapio
Jul 23 '05 #793


Tapio Kelloniemi <sp****@thack.org> writes:
procedure X is

type Metres is new Natural;
type Seconds is new Natural;

M : Metrses := 0;
S : Seconds := 10;
begin
if M < S then -- Error, < is not defined for these types


But now you have problems calculating the velocity, right?

type Velocity is new Natural;
V: Velocity = M/S; // probably a compiler error.


Yes, but I can tell the compiler that I know better:
V : Velocity := Velocity (Integer (M) / Integer (S));


or

function "/" (M : in Metres; S : in Seconds) return Velocity;

Pascal.

--

--|------------------------------------------------------
--| Pascal Obry Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--| http://www.obry.org
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595
Jul 23 '05 #794
Tapio Kelloniemi wrote:
STL is safer, but it cannot always be
used (eg. when interfacing to foreign code).

An example?

Another example:

int* f()
{
int i = 3;
int& l = *(new int);

l = i;
int* p = &i; // Should be int* p = &l;

return p;
}

int main()
{
int* p = f();
*p = 4;
return 0;
}

# g++ -Wall -o temp temp.cc
#

Not even a warning and the program does not crash on my system! Valgrind
revealed the error (and thought it was a G++ bug).

Strictly speaking one shouldn't use such variable names. However this is not easy to check
all those things. C++ aims to be an *enabling* language. For example one could have
written the following code for a system:
int* f()
{
// For setting panel indication.
int *p =reinterpret_cast <int *>(0x148);

// For reading external thermometer
volatile const int *r= reinterpret_cast<volatile const int *>(329);

// ...

return p;
}

int main()
{
int* p = f();
*p = 4;
return 0;
}


--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #795
Ioannis Vranos wrote:
Perhaps you are right. If you have the standard, have a look at 3.9-2,
3.9-4, and 3.9-5 which I think agrees with you.

For thread completeness, I am posting the portable versions of the codes, as things got
clarified in another thread:
#include <new>

class SomeClass
{
};
int main()
{
unsigned char *array= new unsigned char[sizeof(SomeClass)];

SomeClass *p= new(array)SomeClass;

// ...

p->~SomeClass();

delete[] array;
}


#include <iostream>
#include <cstring>

class SomeClass
{
public:

double d;
int i;
float f;
long l;
};
int main()
{
using namespace std;

unsigned char *array= new unsigned char[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

memcpy(array, &obj, sizeof(obj));

SomeClass *p= static_cast<SomeClass *>( static_cast<void *>(array) );

cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";

p->~SomeClass();

delete[] array;
}

#include <iostream>
#include <cstring>
#include <cstddef>

class SomeClass
{
public:

void somefunc() const { std::cout<<"somefunc() was called!\n"; }
};
int main()
{
using namespace std;

SomeClass obj;

unsigned char *p= reinterpret_cast<unsigned char *>(&obj);

unsigned char *array= new unsigned char[sizeof(obj)];

for(size_t i=0; i<sizeof(obj); ++i)
array[i]= p[i];

SomeClass *obj2= static_cast<SomeClass *>( static_cast<void *>(array) );

obj2->somefunc();

obj2->~SomeClass();

delete[] array;
}


--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #796

Peter Koch Larsen wrote:
"Tapio Kelloniemi" <sp****@thack.org> skrev i en meddelelse
news:IQ*****************@reader1.news.jippii.net.. .
Such mistakes as using a pointer to nothing and writing past the array bounds don't often happen in Ada. What makes you believe they happen regularly in C++? I see no real difference here between a good-quality C++ compiler and Ada.
Tapio

/Peter


Is the following permitted in C++?

// file point.cpp

#include <iostream>

int *p = 0;

void fun()
{
int a = 1;
p = &a;
}

int main()
{
fun();
++(*p);
std::cout << *p << '\n';
return 0;
}

My compiler (GCC-3.4.1) doesn't raise any error with "g++ point.cpp
-Wall -W".

Shouldn't it have to complain?

fabio de francesco

Jul 23 '05 #797
fabio de francesco wrote:
Is the following permitted in C++?

// file point.cpp

#include <iostream>

int *p = 0;

void fun()
{
int a = 1;
p = &a;
}

int main()
{
fun();
++(*p);
std::cout << *p << '\n';
return 0;
}

My compiler (GCC-3.4.1) doesn't raise any error with "g++ point.cpp
-Wall -W".

Shouldn't it have to complain?

It is permitted. What you are incrementing above is the value stored in variable a.
Also check this:
#include <iostream>
#include <cstdlib>
#include <csignal>
inline void SigSegVHandler(int signal)
{
using namespace std;

cerr<<"Illegal memory operation!\n"<<"Exiting...\n";

exit(EXIT_FAILURE);
}

int main()
{
using namespace std;

signal(SIGSEGV, SigSegVHandler);

int *p= 0;

++(*p);

return 0;
}
--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #798

fabio de francesco wrote:
Peter Koch Larsen wrote:
"Tapio Kelloniemi" <sp****@thack.org> skrev i en meddelelse
news:IQ*****************@reader1.news.jippii.net.. .
Such mistakes as using a pointer to nothing and writing past the array bounds don't often happen in Ada.
What makes you believe they happen regularly in C++?

I see no real difference here between a good-quality C++ compiler

and Ada.
Tapio

/Peter


Is the following permitted in C++?

// file point.cpp

#include <iostream>

int *p = 0;

void fun()
{
int a = 1;
p = &a;
}

int main()
{
fun();
++(*p);
std::cout << *p << '\n';
return 0;
}

My compiler (GCC-3.4.1) doesn't raise any error with "g++ point.cpp
-Wall -W".

Shouldn't it have to complain?

fabio de francesco


The following is more enjoable:

#include <iostream>

int *p = 0;

void fun()
{
int a = 1;
p = &a;
}

int fun2()
{
int b = 2;
return b *= b;
}

int main()
{
fun();
int c = fun2();
++(*p);
std::cout << *p << '\n';
std::cout << c << '\n';
return 0;
}

[toor@myhost]$ g++ point4.cpp -Wall -W
[toor@myhost]$ ./a.out
5
4

And now, trying to change some output statements:

int main()
{
fun();
int c = fun2();
std::cout << c << '\n';
++(*p);
std::cout << *p << '\n';
return 0;
}

[toor@myhost]$ g++ point4.cpp -Wall -W
[toor@myhost]$ ./a.out
4
12247261

I don't like anymore spending precious time with debuggers.

Ciao,

fabio de francesco

Jul 23 '05 #799

Ioannis Vranos wrote:
fabio de francesco wrote:
Is the following permitted in C++?

// file point.cpp [skip code]
Shouldn't it have to complain?
It is permitted. What you are incrementing above is the value stored in variable a.

Yes, with the only problem that the stack has already released space
reserved for that variable called "a".
Also check this:
#include <iostream>
#include <cstdlib>
#include <csignal>
inline void SigSegVHandler(int signal)
{
using namespace std;

cerr<<"Illegal memory operation!\n"<<"Exiting...\n";

exit(EXIT_FAILURE);
}

int main()
{
using namespace std;

signal(SIGSEGV, SigSegVHandler);

int *p= 0;

++(*p);

return 0;
}
Here you catch and handle a system SIGSEGV signal... I am missing the
point.
Ioannis Vranos

http://www23.brinkster.com/noicys


fabio de francesco

Jul 23 '05 #800

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

Similar topics

20
by: Mediocre Person | last post by:
Well, after years of teaching grade 12 students c++, I've decided to make a switch to Python. Why? * interactive mode for learning * less fussing with edit - compile - link - run - debug -...
14
by: Gabriel Zachmann | last post by:
This post is not strictly Python-specific, still I would like to learn other university teachers' opinion. Currently, I'm teaching "introduction to OO programming" at the undergrad level. My...
3
by: andy_irl | last post by:
Hi there I have been asked to teach HTML to a group in our local village community. It is nothing too serious, just a community development grant aided scheme. It will be a 10 week course of two...
12
by: Pierre Senellart | last post by:
I am going to teach a basic Web design course (fundamentals of HTML/CSS, plus some basic client-side (JavaScript) and server-side (PHP, perhaps XSLT) scripting). Most of the students do not have...
16
by: msnews.microsoft.com | last post by:
I am teaching C# to my 11 year old child. One challenge is that all the C# books I own and that I have seen in bookstores are full of language that is not easily comprehended by a student at that...
24
by: Richard Aubin | last post by:
I'm really new to vb.net programming and programming in general. I would like to teach myself on how to program effectively and I have the financial and time resources to do so. Can I anyone...
0
by: e.expelliarmus | last post by:
check this out buddies. kool website for: * hacking and anti hacking tricks * anti hackng tricks. * registry tweaks * orkut tricks * small virus * computer tricks and loads of different...
1
by: JosAH | last post by:
Greetings, Introduction This week's tip describes a few old tricks that are almost forgotten by most people around here. Sometimes there's no need for these tricks anymore because processors...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...

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

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