By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,905 Members | 1,267 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,905 IT Pros & Developers. It's quick & easy.

I Keep Switching Back...

P: n/a
I'm looking at other languages. Some of them fool me into thinking
they're useful, and I change my home page to them... 'comp.lang.c++'
for instance. But I always end up switching it back to comp.lang.c.
:-D

When I redid my code into C++ recently, I saw some amazing bogosities.
Such as member functions being called before the constructors ran, and
member functions being called for NULL objects. Enough to make me
switch back to C, where function calling order is controlled by the
programmer, and proceeds in a safe and sane order. :-O

So - I'm baaaack. :-D I haven't encountered a good enough language yet
that has made me switch my home page permanently.

--Kamilche
Nov 13 '05 #1
Share this Question
Share on Google+
32 Replies


P: n/a
kl*******@home.com (Kamilche) writes:
When I redid my code into C++ recently, I saw some amazing bogosities.
Such as member functions being called before the constructors ran, and
member functions being called for NULL objects. Enough to make me
switch back to C, where function calling order is controlled by the
programmer, and proceeds in a safe and sane order. :-O


C++ has a really, really scary amount of complexity. Personally,
a few months ago I embarked on trying to learn it well enough to
use it for real projects, by way of buying all the best books on
it and summarizing their advice, with citations, into a "best
practices guide" for myself. So far, I have over 10,000 words
citing 18 books and articles, and I still have quite a way to go.
--
"I am worth much more brick-bat!!"
--Uday Joshi
Nov 13 '05 #2

P: n/a
Kamilche wrote:

I'm looking at other languages. Some of them fool me into thinking
they're useful, and I change my home page to them... 'comp.lang.c++'
for instance. But I always end up switching it back to comp.lang.c.
:-D

When I redid my code into C++ recently, I saw some amazing bogosities.
Such as member functions being called before the constructors ran, and
member functions being called for NULL objects. Enough to make me
switch back to C, where function calling order is controlled by the
programmer, and proceeds in a safe and sane order. :-O

So - I'm baaaack. :-D I haven't encountered a good enough language yet
that has made me switch my home page permanently.

Welcome back. We've missed you.
--
Joe Wright mailto:jo********@earthlink.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 13 '05 #3

P: n/a
Richard Heathfield <do******@address.co.uk.invalid> wrote in message news:<be**********@hercules.btinternet.com>...
Welcome back to the comp.lang.c newsgroup.

We've moved the coffee machine to make room for another server. You'll now
find it in the cafeteria, next to the swing doors.

Your cloakroom peg has been re-assigned, so please apply for a new one when
you pick up your swipe card.

Don't forget to unsubscribe from comp.lang.c++ :-)


:-D
Kamilche plops a plate of cookies next to the water cooler, and
surveys her old digs happily.
Nov 13 '05 #4

P: n/a
Ben Pfaff <bl*@cs.stanford.edu> wrote in message news:<87************@pfaff.Stanford.EDU>...
kl*******@home.com (Kamilche) writes:

C++ has a really, really scary amount of complexity. Personally,
a few months ago I embarked on trying to learn it well enough to
use it for real projects, by way of buying all the best books on
it and summarizing their advice, with citations, into a "best
practices guide" for myself. So far, I have over 10,000 words
citing 18 books and articles, and I still have quite a way to go.


Yeah, I believe it. But when push comes to shove, what I saw looked
and smelt more like bugs than complexity. I saw member functions being
called before the constructor was called, and learned you can't rely
on constructor initialization order for global objects. So I turned
them into pointers instead, and discovered that C++ will call member
functions for objects that DON'T EVEN EXIST. They can be NULL, and you
can still call their functions. The function gets a NULL 'this'
pointer!

The following code compiles and runs, and A() executes. Apparently the
object orientation of C++ is a thin scum over procedural programming,
UNRELIABLE procedural programming at that, to allow code like this to
execute. That's when I put it down and walked away from it.

class My
{
public:
void A()
{
if (this==NULL) printf("NULL Pointer ");
}
};

void main()
{
My *ptr=NULL;
ptr->A();
}

I feel that by going to C++, I'd be giving up the complexities
inherent in large C programs, for the undiscovered bugs in C++... ya
know? I know object oriented programming from other languages, such as
VB... and this is just not the way it should work.

I've been doing a huge amount of experimenting with hierarchical
objected oriented C systems. Right now, I'm looking at code
generation, or possibly heavy use of configuration files, to reduce
complexity... something where I can keep the high level 'big picture'
pseudocode in a text file, and either load it at startup, or auto
generate code from it.
Nov 13 '05 #5

P: n/a
kl*******@home.com (Kamilche) wrote in message news:<88**************************@posting.google. com>...
I'm looking at other languages. Some of them fool me into thinking
they're useful, and I change my home page to them... 'comp.lang.c++'
Currently I mostly use C for my work, but I have some 10 years of C++
experience too. I also like other languages like to study scheme,
haskell et cetera, and my conclusion is that there is no "one
language" that is good for everything. C is a great language,
and so is C++.
When I redid my code into C++ recently, I saw some amazing bogosities.
Such as member functions being called before the constructors ran,
What did you do?

Perhaps something like the following?
Foo* x;
x->member_func();
and
member functions being called for NULL objects.
The caller is responsible for initializing the objects, calling member
functions for NULL objects is just as much undefined behavior as
the "C" constructs:

int i;
i = i++ + ++i;

and

int* i;
*i = 42;
Enough to make me
switch back to C, where function calling order is controlled by the
programmer, and proceeds in a safe and sane order. :-O
You switch to C because you can't handle the responsibility to initialize
the objects before you use them? Perhaps pascal is a better language
for you...
The following code compiles and runs, and A() executes.
It doesn't for me. I get the following compile errors:

~% g++ -pedantic -ansi -Wall asdf.cc
asdf.cc: In method `void My::A()':
asdf.cc:6: `NULL' undeclared (first use this function)
asdf.cc:6: (Each undeclared identifier is reported only once
asdf.cc:6: for each function it appears in.)
asdf.cc:6: `printf' undeclared (first use this function)
asdf.cc: At top level:
asdf.cc:11: warning: return type for `main' changed to `int'

To fix it I have to include <cstdio>, change printf to std::printf, and
change "void main" to "int main".
Apparently the
object orientation of C++ is a thin scum over procedural programming,
UNRELIABLE procedural programming at that, to allow code like this to
execute. That's when I put it down and walked away from it.

class My
{
public:
void A()
{
if (this==NULL) printf("NULL Pointer "); // This can never be NULL, this test is not necessary. }
};

void main()
{
My *ptr=NULL;
ptr->A();
}


Dereferencing a NULL pointer. I don't understand why you are upset.
This is just as undefined behavior in C++ as the following C program
would be:

#include <stdio.h>

typedef void (*Func)(void);

struct Foo {
Func A;
};

int main ()
{
Foo* ptr = NULL;
ptr->Func();
return 0;
}

Anything can happen in the C-program above, including the output
of some text regarding null-pointers.

I can understand arguments about C++ being a complex language
with lots of things happening "under the hood", but supporting such
arguments with code that invokes undefined behavior, and would
do so even in C, if the constructs had been legal in C is silly.

/Niklas Norrthon
Nov 13 '05 #6

P: n/a
On 10 Jul 2003 00:26:13 -0700, kl*******@home.com (Kamilche) wrote:
....

The following code compiles and runs, and A() executes. Apparently the
object orientation of C++ is a thin scum over procedural programming,
UNRELIABLE procedural programming at that, to allow code like this to
execute. That's when I put it down and walked away from it.

class My
{
public:
void A()
{
if (this==NULL) printf("NULL Pointer ");
}
};

void main()
C++ requires int main, just as C does.
{
My *ptr=NULL;
ptr->A();
}


This is undefined behavior in C++. You are dereferencing a NULL pointer,
which is undefined in C++, just as it is in C. As a clc reader, you know
that anything can happen when undefined behavior is invoked, as in the
following analagous C fragment, also dereferencing a NULL pointer.

char* x = NULL,
strcpy(x, "Hello");

Both code fragments could run "normally", format your hard disk, or
cause a power outage in Birmingham, Alabama.

C++ has problems with undefined behavior similar to C. As Ben Pfaff
commented, C++ is also vastly more complicated than C, but if one writes
good, legal code (avoiding undefined behavior, among other things), C++
is a very useful language.

I would suggest that you learn to write legal C++ before you condemn it.

Regards,
Bruce Wheeler

Nov 13 '05 #7

P: n/a
In article <88*************************@posting.google.com>
Kamilche <kl*******@home.com> writes:
Yeah, I believe it. But when push comes to shove, what I saw looked
and smelt more like bugs than complexity. I saw member functions being
called before the constructor was called, and learned you can't rely
on constructor initialization order for global objects.
(This is probably the wrong newsgroup to gripe about such things,
but as far as I am concerned, this ordering problem is just the
tip of the iceberg.)
So I turned them into pointers instead, and discovered that C++ will
call member functions for objects that DON'T EVEN EXIST. They can be
NULL, and you can still call their functions. The function gets a NULL
'this' pointer!
Yes.
The following code compiles and runs, and A() executes. Apparently the
object orientation of C++ is a thin scum over procedural programming ...
Actually, it is a fairly thick layer. But for simple cases like
this one, there is a direct conversion from C++ to C:
class My
{
public:
void A()
{
if (this==NULL) printf("NULL Pointer ");
}
};
(You need to #include at least one header, and the printf here
should really be "std::cout <<", etc. But never mind that.) Here
the "class function" A() that is a member of the data structure
called "My" is obtained simply by gluing together the type ("My")
and the function name ("A"), which you can do manually in C by
spelling it My_A(). Of course, you give up the automatic "if the
type changes, the function name changes too" part that C++ gives
you.
void main()
{
My *ptr=NULL;
ptr->A();
}


This needs to be "int main()" just as in C.

In any case, the C++ compiler here just glues together (in a
more error-resistant way) the name "My" and the name "A", so
this is like writing the C code:

struct My { char dummy; };
/* dummy element required only because C forbids empty struct */

void My_A(struct My *this) {
if (this == NULL)
printf("NULL pointer\n");
}
int main(void) {
struct My *ptr = NULL;
My_A(ptr);
}

If you change member function A to "virtual", it stops working.
This is because a "virtual" member function is not built by name
-- i.e., we no longer just say "well gosh, `ptr' has type `My' so
we just call My_A() and supply `ptr' as a secret argument for the
`this' parameter". Instead, there is now a "virtual function table"
attached to the data type.

This is where C++ actually gives up something you can do manually
in C. For various (good and bad) reasons, the virtual function
table is essentially an operations vector, and the data structures
-- objects of type "My" -- point to the table. So in C we might
now write:

struct ops_for_My {
void (*A)(struct My *this);
};
static struct ops_for_My ops_for_My = { A };
struct My {
struct ops_for_My *vtable;
/* other data elements go here as needed */
};

When you create an actual object of type "My", the compiler will
fill in the "vtable pointer":

/* C code loose-equivalent of the C++ stuff */
ptr = ...;
ptr->vtable = &ops_for_My;

A later call of the form:

ptr->A(); // in C++

translates to the C call:

ptr->vtable->A(ptr);

and if "ptr->vtable" points to the default table, that calls the
default "My_A()" function. (A derived class that overrides the
default My_A() function just requires another ops table, with a
different "A" pointer.)

Although the need is somewhat specialized and occasional, note that
if you have written this in C, you now have a name for the vtable(s)
that implement the "virtual functions" for anything that is, or is
derived from, a "My". Clearly, if ptr==NULL, this:

ptr->vtable->A(ptr);

is not going to work -- but in C, we can do this instead, in
those rare cases where we want to:

ops_for_My.A(NULL);

In C++ one has to resort to any number of workarounds -- not that
they are particularly horrible or anything; but it is annoying to
know that there is a virtual function table all set up, yet you
are not allowed to access it. You *must* have an instance of the
class in order to access that class's virtual function table.
(The easiest workaround is thus to have a static "dummy" instance.)

In any case, both regular "class functions" and "virtual functions"
are easy to do in C, using these techniques. C++ merely automates
some of the drudge-work, avoiding the opportunity to get it wrong,
but also requiring you to give up some control over it.
--
In-Real-Life: Chris Torek, Wind River Systems (BSD engineering)
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://67.40.109.61/torek/index.html (for the moment)
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 13 '05 #8

P: n/a
On 10 Jul 2003 01:30:46 -0700, ni***@passagen.se (Niklas Norrthon)
wrote:

A very nice post.

I posted something similar in a different subthread.

However,
class My
{
public:
void A()
{
if (this==NULL) printf("NULL Pointer ");// This can never be NULL, this test is not necessary.


Actually, 'this' can be NULL, as the method invocation is undefined
behavior if 'this' is NULL. Anything can happen. Some C++
implementations (VC++ in particular) actually have such code in tests in
library code.
}
};

void main()
{
My *ptr=NULL;
ptr->A();
}


Dereferencing a NULL pointer. I don't understand why you are upset.
This is just as undefined behavior in C++ as the following C program
would be:

#include <stdio.h>

typedef void (*Func)(void);

struct Foo {
Func A;
};

int main ()
{
Foo* ptr = NULL;
ptr->Func();
return 0;
}

Anything can happen in the C-program above, including the output
of some text regarding null-pointers.


Correspondingly, anything (including invocation of the method) can
happen in the C++ example above, because it is also undefined behavior.

I can understand arguments about C++ being a complex language
with lots of things happening "under the hood", but supporting such
arguments with code that invokes undefined behavior, and would
do so even in C, if the constructs had been legal in C is silly.

/Niklas Norrthon


Regards,
Bruce Wheeler

Nov 13 '05 #9

P: n/a
Kamilche <kl*******@home.com> wrote:
Ben Pfaff <bl*@cs.stanford.edu> wrote in message news:<87************@pfaff.Stanford.EDU>...
kl*******@home.com (Kamilche) writes:

C++ has a really, really scary amount of complexity. Personally,
a few months ago I embarked on trying to learn it well enough to
use it for real projects, by way of buying all the best books on
it and summarizing their advice, with citations, into a "best
practices guide" for myself. So far, I have over 10,000 words
citing 18 books and articles, and I still have quite a way to go.
Yeah, I believe it. But when push comes to shove, what I saw looked
and smelt more like bugs than complexity. I saw member functions being
called before the constructor was called, and learned you can't rely
on constructor initialization order for global objects. So I turned
them into pointers instead, and discovered that C++ will call member
functions for objects that DON'T EVEN EXIST. They can be NULL, and you
can still call their functions. The function gets a NULL 'this'
pointer!


You somehow drew the conclusion that C++ doesn't allow for programmers
to write buggy software, where would this come from? In C++ as in C
you're responsible for writing legal code, not the language.

The following code compiles and runs, and A() executes. Apparently the
object orientation of C++ is a thin scum over procedural programming,
UNRELIABLE procedural programming at that, to allow code like this to
execute. That's when I put it down and walked away from it.

class My
{
public:
void A()
{
if (this==NULL) printf("NULL Pointer ");
}
};

void main()
{
My *ptr=NULL;
ptr->A();
}

I feel that by going to C++, I'd be giving up the complexities
inherent in large C programs, for the undiscovered bugs in C++... ya
know? I know object oriented programming from other languages, such as
VB... and this is just not the way it should work.


I ask myself, why you want to give up C at all. If C is inappropriate
for a problem, use something different, but if it does the job (or if
you think you can do the job in C) why not just stick with it?

A mechanic wouldn't use a hammer when a screwdriver is needed, allthough
I bet that he/she could solve the job with a hammer too.

--
Z (Zo**********@daimlerchrysler.com)
"LISP is worth learning for the profound enlightenment experience
you will have when you finally get it; that experience will make you
a better programmer for the rest of your days." -- Eric S. Raymond
Nov 13 '05 #10

P: n/a
kl*******@home.com (Kamilche) wrote in message news:<88*************************@posting.google.c om>...

<snipped>

<OT> class My
{
public:
void A()
{
if (this==NULL) printf("NULL Pointer ");
}
};

void main()
int main (void)
{
My *ptr=NULL;
ptr->A();


dereferencing a null pointer, undefined behavior.
the same effect as doing in C the following:
char *s=NULL;

*s++;

<snipped>

goose,
hand, etc :-)
Nov 13 '05 #11

P: n/a
bs*********@hotmail.com (Bruce Wheeler) wrote in message news:<3f**************@news.siemens.at>...
I would suggest that you learn to write legal C++ before you condemn it.


Hey, that's not even my code! :-D I cut n pasted it from one of the
hundreds of thousands of Google hits discussing this particular
problem with C++. Not to worry, you guys all browbeat into me the
correct usage of int main and common C idioms.

It IS kinda funny tho - 'int main' browbeating isn't as common in the
C++ world as it is in the C world. They've got bigger complaints to
fry. :-O

--Kamilche
Nov 13 '05 #12

P: n/a
Chris Torek <no****@elf.eng.bsdi.com> wrote in message news:<be**********@elf.eng.bsdi.com>...
...
In any case, both regular "class functions" and "virtual functions"
are easy to do in C, using these techniques. C++ merely automates
some of the drudge-work, avoiding the opportunity to get it wrong,
but also requiring you to give up some control over it.


Wow, what useful information! Thanks. :-) I'm going to sit and
cogitate on it and see how it can be worked into my app.

Maybe it's time to pull out that 'Object Orientation in C' link I
saved, the one that used vtables but seemed too complex to use. I know
C a lot better now... and I know the beast that awaits in C++. :-|

--Kamilche
Nov 13 '05 #13

P: n/a

On Thu, 10 Jul 2003, Kamilche wrote:

ru**@webmail.co.za (goose) wrote...

dereferencing a null pointer, undefined behavior.
the same effect as doing in C the following:
char *s=NULL;

*s++;
In C, the above code crashes the app, as is proper.


You've never written C on a DOS box, have you?
In C++, the example I posted merrily runs along,
pretending everything is OK.
You've never written C++ on a Unix box, have you?
An advanced C++ programmer told me that C++ was designed
this way to keep the speed up. I don't think design decisions
qualify as undefined behavior. :-|
What? Are you saying that since you intentionally dereferenced NULL,
that *shouldn't* be undefined? [That's silly.] Or are you saying
that your compiler vendor should have added code to the compiler in
order to make a null-pointer dereference more obvious to the user?
[That's not silly, it's moot.] What "design decisions" are you
talking about?
In my opinion, the app
should have crashed instead of happily calling functions with
a NULL pointer.


Why? Isn't a program crash just as bad? Don't both things qualify
as undefined behavior (yes)? Wouldn't both things merit a bug report
and/or loss of your client's business in the Real World (yes)?

Why would you try to compile that program anyway, *knowing* that it
was not correct? (If your answer is: To gain experience - well,
consider yourself gained.)

-Arthur

Nov 13 '05 #14

P: n/a
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> writes:

[responding to me]
For some people, it's hard to accept that they have come to the end
of their productive lives and step aside for the new generation.


Sad that I've come to "the end of my productive life", then, at
the ripe old age of 24.
Nov 13 '05 #15

P: n/a


Kamilche wrote:
But I do have a bit more to add, for those that claim it's my sucky
C++ skills. You know what? I AM fallible and imperfect! I DON'T get
things right the first time! My apps crash, and I have to use the
development environment to track things down! Once I discover what is
wrong, I fix it, run it again, and gain a little bit of wisdom. I
freely admit this.
What books were you using to learn C++?
But what if you get it wrong, and the program KEEPS RUNNING, as in the
example I posted? That's quite a bit larger mess than I had in C.
You seem to be laboring under the misapprehension that C cannot just got
blithely on about its business when you have a gross error in your code.
You ought to know better than that.
Anyways. I see where you're all coming from, calling it 'undefined
behavior.' I'm sure if I understood C++ perfectly, and never made a
coding error, I'd avoid these 'undefined behavior' areas, and have no
problems with C++. But since I AM fallible, I need it to jump up and
bite me in the butt... the first time it runs. I suppose you could
argue that the problem boils down to, C++ doesn't exhibit enough
'DeathStation 9000' behavior for my taste.


Again, EXACTLY the same thing can happen with C. Notably, writing off
the end of an array. That may crash. It may not. It may "work" for two
years, then crash.

Learn the language properly.

Brian Rodenborn
Nov 13 '05 #16

P: n/a
[snips]

On Thu, 10 Jul 2003 12:31:25 -0700, Kamilche wrote:
char *s=NULL;

*s++;


In C, the above code crashes the app, as is proper.


Really? Where does the standard guarantee a crash? Whoops, it doesn't;
the behaviour is undefined. It could crash, it could run, it could set
your hamster on fire. Expecting any particular behaviour is an error on
your part, not the language's.
--
http://rkc.silversapphire.com
Managed Migration from Windows to Linux
Nov 13 '05 #17

P: n/a
Default User <fi********@company.com> wrote in message news:<3F***************@company.com>...
Learn the language properly.


Well, I'll admit, the book I was using, 'Teach yourself C++ in 21
days', left much to be desired. They didn't cover many basic things,
not even the use of the string library.

The undefined constructor initialization order was not mentioned, nor
was the 'you can pass anything in as a pointer and it will
brain-deadedly treat it as an instance of that type, and execute the
member function for it.' If it had, I may have stopped before I'd
wasted too much time. :-D

--Kamilche
Nov 13 '05 #18

P: n/a
Programmer Dude <cj*******@mmm.com> writes:
Ben Pfaff wrote:
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> writes:

For some people, it's hard to accept that they have come to the
end of their productive lives and step aside for the new
generation.


Sad that I've come to "the end of my productive life", then, at
the ripe old age of 24.


Meanwhile, at 48, I've been using C++ quite happily for a couple
years now. I love it! ;-)


It seems that some people are having trouble spotting my sarcasm
directed at ERT.
Nov 13 '05 #19

P: n/a

On Fri, 11 Jul 2003, Ben Pfaff wrote:

Programmer Dude <cj*******@mmm.com> writes:
Ben Pfaff wrote:
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> writes:
> For some people, it's hard to accept that they have come to the
> end of their productive lives and step aside for the new
> generation.

Sad that I've come to "the end of my productive life", then, at
the ripe old age of 24.


Meanwhile, at 48, I've been using C++ quite happily for a couple
years now. I love it! ;-)


It seems that some people are having trouble spotting my sarcasm
directed at ERT.


Hmm. And here I thought Chris was commiserating with you - he's
obviously reached the end of his productive life, if he uses C++
and *likes* it!

;-)
-Arthur

Nov 13 '05 #20

P: n/a
Kamilche wrote:
You know what? I AM fallible and imperfect! I DON'T get things
right the first time! ...
True for us all.
But what if you get it wrong, and the program KEEPS RUNNING, as
in the example I posted? That's quite a bit larger mess than I
had in C.
Are you under the impression that all bugs in a C program cause
noticable symptoms immediately? Surely you know better.
Since C++ doesn't let you rely on the constructor calling order
for global objects, a typical programmer response is to switch
to pointers, so you can control the ordering.
First, a typical C++ programmer's response is probably different.
(Ways of dealing with this are OT here; contact me if you really
want to know.)

Second, global objects are not generally a Good Thing.

Third, if you must have globals and pointers,...
And you know what? I FORGOT to instantiate the global pointer
before use.


....you need--as in any program--to do it right.

--
|_ CJSonnack <Ch***@Sonnack.com> _____________| How's my programming? |
|_ http://www.Sonnack.com/ ___________________| Call: 1-800-DEV-NULL |
|_____________________________________________|___ ____________________|
Nov 13 '05 #21

P: n/a


Kamilche wrote:

Default User <fi********@company.com> wrote in message news:<3F***************@company.com>...
Learn the language properly.


Well, I'll admit, the book I was using, 'Teach yourself C++ in 21
days', left much to be desired. They didn't cover many basic things,
not even the use of the string library.


So you didn't have a book. What would be your opinion of someone
lambasting C when all they was that sort of book?

Try again with Accelerated C++, or The C++ Programming Language.

Brian Rodenborn
Nov 13 '05 #22

P: n/a

"Niklas Norrthon" <ni***@passagen.se> wrote in message

The caller is responsible for initializing the objects, calling member
functions for NULL objects is just as much undefined behavior as
the "C" constructs:

Are you sure? The following C program is defined

#include <stdio.h>

typedef struct
{
int bar;
}FOO;

void foo(FOO *f);

int main(void)
{
foo(0);
return 0;
}

void foo(FOO *f)
{
if(f == NULL)
printf("NULL pointer\n");
}


Nov 13 '05 #23

P: n/a
"Niklas Norrthon" <ni***@passagen.se> wrote in message [d1*************************@posting.google.com], probably --
ma*****@55bank.freeserve.co.uk's software seems to have
omitted the message ID]
The caller is responsible for initializing the objects, calling member
functions for NULL objects is just as much undefined behavior as
the "C" constructs:

[undefined-behavior C stuff snipped]

In article <be**********@newsg2.svr.pol.co.uk>
Malcolm <ma*****@55bank.freeserve.co.uk> writes:Are you sure? The following C program is defined ...


[this time, I snipped the C code]

He was referring to C++ code. In C++, given a class or struct
type T, one can -- just as in C -- do:

T *p = NULL;

Unlike C, however, C++ has a convenient (if slightly gimmicky) bit
of syntax to say "using object p's type, locate a type-T-specific
function and call it, passing p's value as a secret, hidden argument".
That syntax is:

p->func()

(which is of course in conflict with the same syntax that has a
quite different meaning in C; but hold that thought).

As Niklas Norrthon and numerous others have noted, the effect in
C++ of making such a call is defined only when p is a valid value
of type T, and is not NULL. In practice, real C++ compilers will
resolve the call to the T-specific function "T::func()" at compile
time if and only if T::func is not marked "virtual". So -- defined
behavior or not -- non-"virtual" T::func()s get called even if p
is NULL. When T::func() is marked "virtual", however, the link
between source syntax and actual called function is deferred until
runtime, and looked up at that point, so that if p is NULL, the
call tends to fail.

(I outlined the actual mechanisms, and a way to achieve them in
"raw" C, earlier.)

Note that if we do this, in C:

struct S {
void (*func)(void);
};

void f(struct S *p) {
p->func();
}

we have just used the exact same syntax that C++ uses for "member
function" calls to do something quite different. So when you are
reading C++ code and see:

p->func();

you can never be sure what it means without first inspecting the
data members of the class or struct type that was used to declare
"p". The following (rather wretched) C++ code illustrates the
situation:

struct S1 {
void (*func)(void);
};
struct S2 {
int x;
void func() { x = 42; }
};
struct S3 {
virtual void func();
};

void f(struct S1 *p1, struct S2 *p2, struct S3 *p3) {
p1->func(); // Literally calls p1->func(); does not pass p1.
p2->func(); // Just sets p2->x.
p3->func(); // Calls a "virtual" function, which may vary if p3
// is actually part of a derived type. Passes p3.
}

In f(), the first call works just as in C, calling through p1->func.
The second call sets p2->x to 42, and the third call indirects
through p3's "vtable", which is much like the indirect call for
p1, but using compiler magic rather than an explicit indirect.
You must look up each of the three "struct"s to see which of the
three possible behaviors is being invoked. (This is, of course,
no worse than deciding which overloaded function or operator is
called, in the general case. The concept itself is sensible enough
too: the idea is that you are not supposed to care -- nor have to
care -- which of the various mechanisms is involved. My own
experience has been that you *do* have to care, though, and that
C++ code often[%] lacks sufficient "local" clues to tell you which
one you are getting. Perhaps better compile-time tools would help:
one could click on a "+" operator, for instance, and immedately be
told "this invokes the `add single-precision complex number to
matrix holding string data' function", or whatever. Of course this
does not work for runtime bindings, unless the compiler can somehow
prove that a given variable has some fixed datatype.)

[% "Often" here really means "somewhat rarely, but too often to
just ignore" :-) ]
--
In-Real-Life: Chris Torek, Wind River Systems (BSD engineering)
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://67.40.109.61/torek/index.html (for the moment)
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 13 '05 #24

P: n/a


Chris Torek wrote:
As Niklas Norrthon and numerous others have noted, the effect in
C++ of making such a call is defined only when p is a valid value
of type T, and is not NULL. In practice, real C++ compilers will
resolve the call to the T-specific function "T::func()" at compile
time if and only if T::func is not marked "virtual". So -- defined
behavior or not -- non-"virtual" T::func()s get called even if p
is NULL. When T::func() is marked "virtual", however, the link
between source syntax and actual called function is deferred until
runtime, and looked up at that point, so that if p is NULL, the
call tends to fail.

All of which reinforces what people have been trying to tell Kamilche,
comparing the reaction of different implementations to undefined
behavior is silly. Also, relying on some sort of consistent handling of
undefined behavior as a programming practice is downright foolish.

The newbie chant, "Why didn't it crash like it's supposed to!"


Brian Rodenborn
Nov 13 '05 #25

P: n/a
In article <3F***************@company.com>, fi********@company.com says...
The newbie chant, "Why didn't it crash like it's supposed to!"


Or the much more insidious "Hey, it didn't crash like you said it
would, so it must be perfectly ok. I thought you were a C expert?"
--
Randy Howard
(remove the obvious bits from my address to reply.)
"Most of the drivers nowadays are a bit like Eddie Irvine, who if
he was half as fast as he thought he was, would be moderate."
-- Sir Stirling Moss
Nov 13 '05 #26

P: n/a
In <3F***************@company.com> Default User <fi********@company.com> writes:
All of which reinforces what people have been trying to tell Kamilche,
comparing the reaction of different implementations to undefined
behavior is silly. Also, relying on some sort of consistent handling of
undefined behavior as a programming practice is downright foolish.


I don't think anyone advocated that. However, we do make mistakes. And
it's a lot more helpful for a null pointer to cause a program crash when
dereferenced than to silently let the program continue as if nothing bad
has happened. OTOH, there is the issue of run-time overhead involved in
detecting the indirection through a null pointer (we don't want our
correct program to take a performance hit because of it, either).

Ideally, an implementation would have two modes: a debug mode, where as
many checks as (reasonably) possible are done at run time and a production
mode, where no check is performed at all, the program being assumed to be
correct. All we actually have is assert(), to implement the two modes in
our own code, but we're too lazy to use it as often as necessary
(and a fully assert-instrumented code doesn't look very well, either).

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #27

P: n/a
Da*****@cern.ch (Dan Pop) wrote in message news:<be**********@sunnews.cern.ch>...
In <ff**************************@posting.google.com > ru**@webmail.co.za (goose) writes:
kl*******@home.com (Kamilche) wrote in message news:<88*************************@posting.google.c om>...
ru**@webmail.co.za (goose) wrote in message news:<ff**************************@posting.google. com>...

> dereferencing a null pointer, undefined behavior.
> the same effect as doing in C the following:
> char *s=NULL;
>
> *s++;

In C, the above code crashes the app,
are you sure ? lets find out ...


It doesn't hurt to engage your brain when trying to find out.


it wont hurt for you to do the same :-)

look at what I was responding to above ... (i've not
snipped anything in this post).

the whole point of my response was that Kamliche's statement
"In C, the above code crashes the app" was just plain wrong.

bearing in mind the code she was referring to was
char *s=NULL;

*s++;
[LManickum@lee] Fri Jul 11 12:04:27 [1 bg] /tmp
17 ok cat ./foo.c
#include <stdio.h> /* for NULL */


You also need it for printf().
int main (void) {
char *s=NULL;
*s++;
printf ("no crash\n");
return 0;
}
[LManickum@lee] Fri Jul 11 12:04:32 [1 bg] /tmp
18 ok gcc -ansi -Wall -pedantic foo.c -o foo
foo.c: In function `main':
foo.c:5: warning: value computed is not used


The compiler has clearly told you that you created an idiotic test
program which need not perform the illegal operation at all, because
its result is discarded.

thats the point. it need not have performed any illegal operation
at all, which is why I posted it. Kamilche was under the impression
that it *would* *crash*.
goose,
hand
Nov 13 '05 #28

P: n/a


Dan Pop wrote:

In <3F***************@company.com> Default User <fi********@company.com> writes:
All of which reinforces what people have been trying to tell Kamilche,
comparing the reaction of different implementations to undefined
behavior is silly. Also, relying on some sort of consistent handling of
undefined behavior as a programming practice is downright foolish.
I don't think anyone advocated that. However, we do make mistakes. And
it's a lot more helpful for a null pointer to cause a program crash when
dereferenced than to silently let the program continue as if nothing bad
has happened. OTOH, there is the issue of run-time overhead involved in
detecting the indirection through a null pointer (we don't want our
correct program to take a performance hit because of it, either).


Well, that's an implementation decision. In spite of what some people on
CLC think, the designers and implementors of C++ aren't buffoons. If
they decided that it was best to allow a certain behavior with null
pointers, there is quite probably a good reason for it. Frankly, and
I've been working in C++ for some time, I was unaware of that particular
feature. That was one hell of a description by Chris Torek.
Ideally, an implementation would have two modes: a debug mode, where as
many checks as (reasonably) possible are done at run time and a production
mode, where no check is performed at all, the program being assumed to be
correct. All we actually have is assert(), to implement the two modes in
our own code, but we're too lazy to use it as often as necessary
(and a fully assert-instrumented code doesn't look very well, either).


Sure. It's an important programming requirement (like I need to tell
you) to consider the behavior of the program under development when
presented with invalid pointers. About the only thing you can reasonably
check is for null pointers. Using assert is a pretty good way to weed
out the design errors that can result in a null. You hope that your
testing does find all the ways that such a thing can happen. That's were
good unit testing and integration comes into play.
There are perfectly valid reasons for prefering one programming language
over another. I just thought that Kamilche's reason for abandoning C++
amounted to a frivilous one, and that she didn't really make that much
effort to learn C++.


Brian Rodenborn
Nov 13 '05 #29

P: n/a
Ben Pfaff wrote:
For some people, it's hard to accept that they have come to the
end of their productive lives and step aside for the new
generation.

Sad that I've come to "the end of my productive life", then, at
the ripe old age of 24.


Meanwhile, at 48, I've been using C++ quite happily for a couple
years now. I love it! ;-)


It seems that some people are having trouble spotting my sarcasm
directed at ERT.


My comment was likewise directed at ERT (not you).

--
|_ CJSonnack <Ch***@Sonnack.com> _____________| How's my programming? |
|_ http://www.Sonnack.com/ ___________________| Call: 1-800-DEV-NULL |
|_____________________________________________|___ ____________________|
Nov 13 '05 #30

P: n/a
In <ff**************************@posting.google.com > ru**@webmail.co.za (goose) writes:
Da*****@cern.ch (Dan Pop) wrote in message news:<be**********@sunnews.cern.ch>...
In <ff**************************@posting.google.com > ru**@webmail.co.za (goose) writes:
>kl*******@home.com (Kamilche) wrote in message news:<88*************************@posting.google.c om>...
>> ru**@webmail.co.za (goose) wrote in message news:<ff**************************@posting.google. com>...
>>
>> > dereferencing a null pointer, undefined behavior.
>> > the same effect as doing in C the following:
>> > char *s=NULL;
>> >
>> > *s++;
>>
>> In C, the above code crashes the app,
>
>are you sure ? lets find out ...
It doesn't hurt to engage your brain when trying to find out.


it wont hurt for you to do the same :-)


Unlike you, I did!
look at what I was responding to above ... (i've not
snipped anything in this post).


It was a schematic example, not supposed to be taken ad litteram.
But you completely missed this aspect, for the above mentioned reason
(that is, unless you're a genuine idiot ;-)

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #31

P: n/a
Da*****@cern.ch (Dan Pop) wrote in message news:<bf**********@sunnews.cern.ch>...
In <ff**************************@posting.google.com > ru**@webmail.co.za (goose) writes:
Da*****@cern.ch (Dan Pop) wrote in message news:<be**********@sunnews.cern.ch>...
In <ff**************************@posting.google.com > ru**@webmail.co.za (goose) writes:

>kl*******@home.com (Kamilche) wrote in message news:<88*************************@posting.google.c om>...
>> ru**@webmail.co.za (goose) wrote in message news:<ff**************************@posting.google. com>...
>>
>> > dereferencing a null pointer, undefined behavior.
>> > the same effect as doing in C the following:
>> > char *s=NULL;
>> >
>> > *s++;
>>
>> In C, the above code crashes the app,
>
>are you sure ? lets find out ...

It doesn't hurt to engage your brain when trying to find out.


it wont hurt for you to do the same :-)


Unlike you, I did!
look at what I was responding to above ... (i've not
snipped anything in this post).


It was a schematic example, not supposed to be taken ad litteram.
But you completely missed this aspect, for the above mentioned reason
(that is, unless you're a genuine idiot ;-)


ah, its /clearer/ now ...
("ad litteram" == "literally" ???)

goose,
not the *genuine* article, just a wannabe idiot :-)
Nov 13 '05 #32

P: n/a
In <ff*************************@posting.google.com> ru**@webmail.co.za (goose) writes:
("ad litteram" == "literally" ???)


"ad litteram" (Latin expression adopted by English) is less ambiguous
than "literally":

Main Entry: literally
Function: adverb
Date: 1533
1 : in a literal sense or manner : ACTUALLY <took the remark literally>
<was literally insane>

2 : in effect : VIRTUALLY <will literally turn the world upside down
to combat cruelty or injustice -- Norman Cousins>

usage: Since some people take sense 2 to be the opposite of sense 1,
it has been frequently criticized as a misuse. Instead, the use is
pure hyperbole intended to gain emphasis, but it often appears in
contexts where no additional emphasis is necessary.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #33

This discussion thread is closed

Replies have been disabled for this discussion.