HDTenEightyP/NetNews huggingface dataset:
From: dalle@diab.se (Jan-Erik Dahlin)
Newsgroups: comp.std.c++
Subject: Incomplete types and nested classes
Date: 7 Sep 92 19:01:32 GMT
Distribution: comp
Organization: Diab Data AB

steve@taumet.com (Steve Clamage) recently wrote about forward declaration
of nested classes:

> You do it the same way you handle any other forward declaration.
> You have to be careful about scopes.
> 
> 	class A {
> 	  public:
> 	    class C;	// forward declaration of A::C
> 	    class B {
> 		C *p;	// pointer to A::C
> 	    };
> 	    class C {
> 		B *p;	// pointer to A::B
> 	    };
> 	};
> 

How about incomplete types and nested classes? What happens if we skip
the first declaration of class C? I ran into the problem when compiling
some old C code.

Section 9.1, paragraph 2 of the draft says: "A class declaration
introduces the class name into the scope where it is declared and hides
any class, object, function or other declaration of that name in an
enclosing scope."

Paragraph 3: "An elaborated-type-specifier can also be used in the
declarations of objects and functions. It differs from a class
declaration in that if a class of the elaborated name is in scope the
elaborated name will refer to it." 

What happens if no class with that name is found in scope???

Paragraph 4 has the following example: "A name declaration takes effect
immediately after the identifier is seen. For example,

	class A * A;

first specifies A to be the name of a class and the redefines it as
the name of a pointer to an object of that class."

I guess this means that class A is introduced into the current scope if
not defined earlier.

Example:

 	class A {
 	  public:
 	    class B *bp; // pointer to A::B or B?
	    f(void);
 	};

 	class B {
	  public:
 	    int memb;
 	};

	A::f()
	{
	    bp->memb = 4711;	// Is this legal?
	}

When the elaborated class specifier for B is seen, should the name be
introduced in the scope of class A (as in a nested class declaration)
or the scope enclosing A?

I think that the declaration 'class B *bp;' should introduce (a nested)
class B in the scope of A. The declaration of class B will introduce a
new type in the file/global scope. When 'bp' is used in A::f() it is a
pointer to the local class B in A's scope, which still is incomplete.
Since both Cfront and gcc accept the above declarations without complaint
I assume I've misinterpreted the standard. Could someone, please,
straighten things out for me?

> 
> Steve Clamage, TauMetric Corp, steve@taumet.com
> Vice Chair, ANSI C++ Committee, X3J16

							/Jan-Erik Dahlin
--
"Sometimes the magic works and sometimes it doesn't."
 Chief Dan George of the Sioux Indian tribe, after an unsuccessful rain dance.
Xref: sparky comp.std.c++:1176 comp.lang.c++:13607
From: bs@alice.att.com (Bjarne Stroustrup)
Newsgroups: comp.std.c++,comp.lang.c++
Subject: Re: Exponentiation operator proposal
Date: 14 Sep 92 14:27:49 GMT
Article-I.D.: alice.23663
Organization: AT&T Bell Laboratories, Murray Hill NJ



karl@ima.isc.com (Karl Heuer) writes

 > >(2) I think we could actually get ** as the exponentiation operator.
 > >[By defining `**' to have semantics of TIMES FETCH when the right operand
 > >is a pointer]

 > I considered this when I wrote my exponentiation essay.  I decided that it
 > might be possible, but it's way too confusing!  This would be a kludge of the
 > highest order.  It's much better to use syntax that's not already taken --
 > I've adopted "*^", as suggested by someone else some years ago.  (A hybrid of
 > "**" and "^", sort of.)

Of course it is a hack. It is a compatibility hack of the first order,
but I see few TECHNICAL problems with it.

and  rr@world.std.com (Robert I Ransbottom) writes

 > I agree ** is confusing, given the potential frequency of both "dat**ptr" and
 > "dat**dat" it seems like a waste to deciphering such.  The proponents
 > of **expon want a convenience. 
 > 
 > I think that ^^ would be more satisfying to both pointer-ers and math-ers.  
 > 
 >     1. Its not already taken!
 >     .   .   .    .      .
 >     n. Its easier to type than Karl's *^. 

The reason I mentioned ** is that I think that every alternative mentioned
so far has something wrong with it. I see ^ as xor and ^^ bothers me.
As it happens *^ doesn't bother me but my feeling was that 99% of the
deamand for an exponentiation operator comes from current or past Fortran
users and - in my experience - they always ask for ** and are unsatisfied
with the explanations of why they can't have that syntax.

How frequent is a**p anyway? (has anyone got any data?) How confusing
would it really be? Many people use spaces to clarify (to their eyes,
if not to everyone else's) code, e.g. a * *p. Also, not all overloading
creates confusion, especially when identifier names are chosen with
a minimum of care (want would x**e mean? a**xptr mean?). I doubt the
case is clear cut.

I am not arguing that ** is THE right solution, but that given the
demand for it and the lack of ginuinely nice alternatives ** should
not be written off without a thought and/or in the belief that it
is technically infeasible to provide it.
From: dat@thinkage.on.ca (David Adrien Tanguay)
Subject: Re: Operations on Files
Keywords: ANSI C, files
Organization: Thinkage, Ltd.
Date: Sun, 6 Sep 1992 23:08:23 GMT

robertl@county.lmt.mn.org (ROBERT LAUMEYER) writes:
>
>	The ANSI C standard seems to have a rather odd mix of file 
>operations.  Why didn't they add (over K&R) some other useful file 
>operations such as fileexist, getfirst, getnext, etc?  It seems that 
>these could not be much more dependent on the underlying file system than 
>rename or remove.

These routines assume a directory structure, i.e., that there is such a
concept as sub-structure. Other forms of file organization are reasonable.
For example, the files could be organised as a relational database, where you
don't really navigate from one node to another. Or, a file could be a point
in n-space. Stuff like this pops up in videotext systems.
-- 
David Tanguay       dat@Thinkage.on.ca  dat@Thinkage.com  uunet!thinkage!dat
Thinkage, Ltd.           Kitchener, Ontario, Canada          [43.40N 80.47W]
Newsgroups: comp.std.c
From: dat@thinkage.on.ca (David Adrien Tanguay)
Subject: Re: struct hack, and other out-of-array references
Organization: Thinkage, Ltd.
Date: Thu, 10 Sep 1992 21:32:40 GMT

msb@sq.sq.com (Mark Brader) writes:
>The pointer f->s does point to an object with type char[1], but it is
>also a pointer into the space returned by malloc(), which may be treated
>as an array of chars.  That is, when strcpy computes the equivalent of
>(f->s)[1], and therefore (f->s)+1, both the pointer operand of +, i.e.
>f->s, and the computed result *are* within the same array, namely the one
>returned by malloc(), and all is well.

How is this any different from the array example?

	struct { int i; char s[1]; } *f = malloc(sizeof(*f)+10);
	int a[6][6];
	int *p = a[1];
	p += 7;   /* is this well-defined? */

If it is not defined, then it is the same as the struct hack. p may now point
outside a[1], but it is still within the a object. Similarly, 
	char *q = fs->s;
	q += 2;
is outside the f->s object but within the malloc object.

Also, I don't see how a[1][7] is any different from f->s[2]. The f->s object,
determined by the "type and value", ends at f->s+1. Note that this case is
different from the q case, above, since the type of q is different from the
type of f->s.

(The interpretation, however, does deal only with arrays. We're extending the
same reasoning to apply to structure elements, hoping for consistency.)

>I would also argue that the Interpretation Ruling cited above would not
>apply if the type of the example array "a" had been char instead of int.
>The definitions of "object" and "byte" (in ANSI section 1.6, ISO 3.14 and
>3.4) in effect require that it be possible to treat any object as an
>array of any character type.  This guarantee is assumed, of course, by
>any number of library functions.  Once again, this should render legal any
>references that are out of bounds in a subarray but which address locations
>known to be in the containing array.

I don't see how this necessarily follows. "char *cp = a" would be allowed
to range throughout a, satisfying 3.4, but "char *cp = a[1]" may be limited
to ranging over the a[1] object.

I think this really is a matter of "interpretation": what is the "object"
to which a pointer points? The object determined by the type of the
originating pointer expression, or the largest C object containing the value
originating pointer expression?
-- 
David Tanguay       dat@Thinkage.on.ca  dat@Thinkage.com  uunet!thinkage!dat
Thinkage, Ltd.           Kitchener, Ontario, Canada          [43.40N 80.47W]
Newsgroups: comp.std.c,comp.std.c++
From: mjn@pseudo.uucp (Murray Nesbitt)
Subject: Re: Zero-length structures and pointer comparisons
Organization: Private system in Toronto, ON
Date: Wed, 9 Sep 1992 19:38:42 GMT


fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON) writes:

>is the following a legal (strictly conforming) program?
>
>	struct S { unsigned:0; }
>	int main() { return sizeof(S); }

It is not a legal C program, but not due to any particular ANSI
constraints.  It has syntax errors.  Perhaps you meant:

	struct S { unsigned:0; };
	int main() { return sizeof(struct S); }

-- 
Murray
Newsgroups: comp.std.c
From: diamond@jit345.bad.jit.dec.com (Norman Diamond)
Subject: Re: POSIX version of chsize/ftruncate?
Reply-To: diamond@jit.dec.com (Norman Diamond)
Organization: Digital Equipment Corporation Japan , Tokyo
Date: Tue, 15 Sep 1992 04:14:37 GMT

In article <BuL6E4.2wq@csn.org> c4craig@teal.csn.org (Craig Anderson) writes:
>How should I port a DOS call to chsize() to STD C / POSIX?
>In SunOS and BSD/386 I find:
>int ftruncate(int fd, off_t length)
>  truncate a file to a specified length

I hope that the POSIX standard has ftruncate(), but let's hope this will
be answered by someone who knows.

If you want to be portable to most ANSI C implementations (including those
which are not POSIX conforming) then the answer is ugly.  Use fopen() to
create a new file with some name that you think will be acceptable (e.g.
will be located on the same physical device and partition and probably
directory as the old file), copy the contents of the old file to the new
one, stop where you want it truncated, fclose() the new file, remove() the
old one, and rename() the new one.  There is no guarantee that this will
work (disk space might be exceeded or the implementation can return failure
status for any reasons it wishes) but this is as close as you can get.
This will probably lose the file permissions and various other OS-dependent
stuff that were set on the old file.

I would define a few flags at compile time and do stuff like
#if have_unix_fds && have_ftruncate
  status = ftruncate(fileno(my_file), where);
#else
  all that garbage
#endif

>In DOS Turbo C++ I find:
>int chsize(int handle,k long size)
>  Changes the file size.

If you only want to port to POSIX conforming systems, you'll have UNIX-style
file descriptor numbers (which are probably the same as handles) and, I hope,
ftruncate.  If you want to port to all ANSI C implementations, you'll have
to change all of your handles to use stdio-style files.
--
Norman Diamond       diamond@jit081.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
"Yeah -- bad wiring.  That was probably it.  Very bad."
Newsgroups: comp.std.c
From: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Subject: Re: struct hack, and other out-of-array references
Organization: Computer Science, University of Melbourne, Australia
Date: Fri, 11 Sep 1992 14:07:47 GMT

flaps@dgp.toronto.edu (Alan J Rosenthal) writes:

>dat@thinkage.on.ca (David Adrien Tanguay) writes:
>>How is this any different from the array example?  p may point
>>outside a[1], but it is still within the a object.  Similarly, ...
>>is outside the f->s object but within the malloc object.
>
>The point is, "int a[5][5];" doesn't give you 25 ints, it gives you five arrays
>of five ints each.  "(int(*)[5])malloc(5*sizeof(int[5]))" gives you
>sizeof(int)*25 bytes which are ALSO five arrays of five ints.
>
>The first looks like this:
>	int[5][5]:
>	    int[5]:
>		int
>		int
>		int
>		int
>		int
>	    int[5]:
>		...
>	    ...
>
>And the second looks like this:

     malloc(25):
>	char
>	char
>	char
>	char
>	...
>
>Now that cast magically makes the second be close enough to the first in
>outward appearance for all intents and purposes, but it's still the second
>underneath.  Obviously in almost all compilers the memory layout will be the
>same.  However, an environment such as Saber-C should be free to keep track of
>the details and that's why I've always thought that this is a good
>interpretation ruling.
>
>I'm not sure what you get when you take a pointer to that array five of array
>five of int, cast it to a (char *), then cast it to a (int(*)[5]).

This sounds like a fairly reasonable explanation, but I still have some
questions.

Do same considerations would apply if you tried to use a char[5][5] 
array as a char[25] array? It sounds like you would say they
do. What about casting a char[25] array to a char[5][5] array?

From what you're saying, the reason that casting the return
value from malloc succeeds is only because malloc is "magic".

-- 
Fergus Henderson             fjh@munta.cs.mu.OZ.AU      
This .signature virus is a self-referential statement that is true - but 
you will only be able to consistently believe it if you copy it to your own
.signature file!
Newsgroups: comp.std.c,comp.std.c++
From: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Subject: Zero-length structures and pointer comparisons
Organization: Computer Science, University of Melbourne, Australia
Date: Tue, 8 Sep 1992 16:14:16 GMT

First, a question for comp.std.c:
is the following a legal (strictly conforming) program?

	struct S { unsigned:0; }
	int main() { return sizeof(S); }

Secondly, some comments about C++.
In ANSI C, pointer comparisons between pointers to unrelated objects (ie.
objects that are not both members of the same aggregate) cause undefined
behavior, I believe. For example, the following program
	#include <assert.h>
	int main() {
		int x,y;
		assert(&x != &y);
	}
should cause undefined behavior. [Is this correct?]

Now the C++ reference manual (5.9) says basically the same thing, with the
further constraints that comparisons with pointers to static members are
undefined, as are comparisons between pointers to members whose declarations
are separated by an access-class specifier (public/protected/private).

Section 5.9 says that "Two pointers to the same object compare equal",
but it does NOT say that "pointers to distinct objects compare unequal" -
instead it says "... Other pointer comparisons are implementation dependent."

Given that this is the case, it seems contradictory that repeated calls to
operator new(0) are required to return pointers to "distinct objects".
How could a conforming program possibly detect whether this requirement
was actually met? Surely the following program
	#include <assert.h>
	int main() {
		assert(operator new(0) != operator new(0));
	}
is not strictly conforming, is it?

-- 
Fergus Henderson             fjh@munta.cs.mu.OZ.AU      
This .signature virus is a self-referential statement that is true - but 
you will only be able to consistently believe it if you copy it to your own
.signature file!
Newsgroups: comp.std.c
From: berg@physik.tu-muenchen.de (Stephen R. van den Berg)
Subject: Re: struct hack, was Re: strcpy implementation question
Originator: berg@tabaqui
Organization: Rechnerbetrieb Informatik  /  RWTH Aachen
Date: Tue, 8 Sep 92 12:46:55 GMT

Clive Feather writes:
>diamond@jit081.enet.dec.com writes:
>>David Adrien Tanguay writes:
>>>diamond@jit081.enet.dec.com writes:
>>>>Israel Pinkas writes:
>>>>> The variable length struct is a hack.  There is nothing in the language that
>>>>> prevents the compiler from performing bounds checking on accesses to name.
>>>> Bounds checking is not allowed to affect output of a valid but ugly program.
>>> I had the impression that the last time it came up here the conclusion was
>>> that this trick was not sanctioned[...]  3.3.6 "Additive Operators"
>>> says that you aren't guaranteed to go past the end of an array object,
>> No (though it was the conclusion of some others) and yes, respectively.
>> You can't go past the end of an array object.  But if malloc() or some other
>> variable has defined the end of the actual array object, then the + operator
>> can get you that far, regardless of the declared type that some other array
>> variable had before getting flattened to a pointer.

>But there is an intepretation that says that, given

>    int a [5][5];

>the access "a [1][6]" is illegal, because it goes past the bounds of the
>array "a [1]". In other words, the declared type of the array does
>restrict what can happen to a pointer derived from it.

Correct, but:

	int a[5][5]; int*p;

	p=a[1]+5;

	printf("a[2][0]=a[1][6]=%d\n",*++p);

sure seems to be allowed (although not recommended).
-- 
Sincerely,                                  berg@pool.informatik.rwth-aachen.de
           Stephen R. van den Berg (AKA BuGless).    berg@physik.tu-muenchen.de

"And now for something *completely* different!"
From: diamond@jit081.enet.dec.com (09-Sep-1992 1034)
Newsgroups: comp.std.c
Subject: Re: Zero-length structures and pointer comparisons
Date: 9 Sep 92 01:35:05 GMT

In article <9225302.22791@mulga.cs.mu.OZ.AU> fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON) writes:
>First, a question for comp.std.c:
>is the following a legal (strictly conforming) program?
>       struct S { unsigned:0; }
>       int main() { return sizeof(S); }

No.  ANSI C section 3.5.2.1, page 61 lines 25 to 26:  "If the
struct-declaration-list contains no named members, the behavior is undefined."

>Secondly, some comments about C++.
>In ANSI C, pointer comparisons between pointers to unrelated objects (ie.
>objects that are not both members of the same aggregate) cause undefined
>behavior, I believe. For example, the following program
>       #include <assert.h>
>       int main() {
>               int x,y;
>               assert(&x != &y);
>       }
>should cause undefined behavior. [Is this correct?]

No.  For relational operators (<, >, <=, >=) that would be correct.
For equality operators (==, !=) the result is defined.  Comparing whether
a pointer is equal to a null pointer or not is a common operation, and
(unless miscoded in some other way) is defined.

I don't have modern documents on C++ and don't dare to answer your later
questions.  For the same reason, this answer is not cross-posted.
--
Norman Diamond       diamond@jit081.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
"Yeah -- bad wiring.  That was probably it.  Very bad."
From: jfw@ksr.com (John F. Woods)
Newsgroups: comp.std.c
Subject: Re: Zero-length structures and pointer comparisons
Date: 8 Sep 92 17:39:12 EDT

fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON) writes:
>First, a question for comp.std.c:
>is the following a legal (strictly conforming) program?
>	struct S { unsigned:0; }
>	int main() { return sizeof(S); }

No.  "If the struct-declaration-list contains no named members, the behavior
is undefined."  This is not a Constraint, so no message is required by the
Standard; the compiler can do something arbitrarily cruel and stupid without
even giving a hint as to what it is up to :-).

Newsgroups: comp.std.c
From: henry@zoo.toronto.edu (Henry Spencer)
Subject: Re: calloc()
Date: Thu, 10 Sep 1992 16:33:49 GMT
Organization: U of Toronto Zoology

In article <14455@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:
>Now I wonder:  if I want to allocate an array with elements of known size
>but with number of elements not known until run-time, and if I don't really
>care what the initial contents are, _is_ there something in the standard to
>make
>	p = calloc(NumberOfElements, sizeof *p)
>better than
>	p = malloc(NumberOfElements * sizeof *p) ?

No.

Calloc() is pretty useless, actually; the initialization it does is usually
superfluous, isn't particularly portable (all-0-bits isn't necessarily a
zero floating-point number or a NULL pointer), and isn't cheap.  Otherwise
it's a synonym for malloc() with a slightly different calling convention.
Its presence is basically a historical accident.
-- 
There is nothing wrong with making      | Henry Spencer @ U of Toronto Zoology
mistakes, but... make *new* ones. -D.Sim|  henry@zoo.toronto.edu  utzoo!henry
Newsgroups: comp.std.c,comp.std.c++
From: oherb@jhunix.hcf.jhu.edu (Zoher B Bambot)
Subject: Re: Zero-length structures and pointer comparisons
Organization: HAC - Johns Hopkins University, Baltimore
Date: Thu, 10 Sep 1992 20:36:35 GMT

Hi! I had posted this earlier but due to no suitable response I am posting it
again. I would gratefully acknowledge a reply in this matter.

I am working on developing classes for simulation of finite element meshes
using the object-oriented language c++. I would be grateful if anyone could
send me any programs in c++ which would help me in my work. Also has anyone 
developed a class for the simulation of a FEM for any particular structure.
You can mail them to me at my e-mail address and then I will summarize in
the net. Also are there any ftp sites from where I could get any useful
information. Thanx in advance.
                         Zoher.( oherb@jhunix.hcf.jhu.edu )
Newsgroups: comp.std.c
From: steve@taumet.com (Steve Clamage)
Subject: Re: calloc()
Organization: TauMetric Corporation
Date: Thu, 10 Sep 1992 18:05:42 GMT

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:

>Now I wonder:  if I want to allocate an array with elements of known size
>but with number of elements not known until run-time, and if I don't really
>care what the initial contents are, _is_ there something in the standard to
>make
>	p = calloc(NumberOfElements, sizeof *p)
>better than
>	p = malloc(NumberOfElements * sizeof *p) ?

No.  The only required difference is the calling sequence and that
calloc clears the memory to all bits zero.

That said, suppose we have a system where int and size_t are 16 bits,
but it is possible to allocate an object bigger than 64K.  A
careful library implementor would ensure that a call like
	calloc(68, 1000)
did not result in integer overflow inside calloc, but would allocate
68000 bytes.  You couldn't do that with (ordinary) malloc.  (I
actually had to implement this on a pre-Standard system one time.)
I don't think the Standard requires this sort of care, but I would
expect it from a quality implementation.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com
Vice Chair, ANSI C++ Committee, X3J16
Xref: sparky comp.std.c:2639 comp.lang.c:13715