Tuesday, January 14, 2020

Digest for comp.lang.c++@googlegroups.com - 25 updates in 7 topics

Frederick Gotham <cauldwell.thomas@gmail.com>: Jan 14 05:38AM -0800

NOTE: Usenet has been around since 1979/1980. In these past 40 years, people have taken likings and dislikings to cross-posting and multi-posting. Irrespective of my own preference, it is clear to me from being on Usenet since about 2002 that far more people dislike cross-posting. I have therefore multi-posted to two groups, a C one, and a C++ one.
 
A few months ago I posted about my generic Makefile that builds a C/C++ program from all the source files in the current directory. I've been using this Makefile for the past few months on loads of different programs (big and small) and it works well.
 
Moving on. . .
 
What would be the best way to implement "make install" as portably and generically as possible? Here's what I've got so far:
 
#If DESTDIR is not set then set it
ifeq ($(DESTDIR),)
DESTDIR = /usr/bin
endif
 
.PHONY: install
install: $(PROGRAM)
cp $< $(DESTDIR)
 
.PHONY: uninstall
uninstall:
$(RM) $(DESTDIR)/$(PROGRAM)
 
 
I have seen some people use the environment variable "PREFIX" in their makefiles but I'm not sure if it would do here. Should I even bother trying to implement this for Microsoft? For example I could copy the file to "c:\Program Files".
 
 
Oh by the way here's the entire Makefile. It's written to be as flexible as possible (for example if the user does make SOME_VARIABLE=some_value):
 
PROGRAM = prog
 
INC_DIRS += -I./
 
CFLAGS_CXXFLAGS_IN_COMMON += -pedantic -Wall -Wextra -rdynamic -funwind-tables -fno-omit-frame-pointer -fdump-rtl-expand -fno-common
CFLAGS += $(INC_DIRS) $(CFLAGS_CXXFLAGS_IN_COMMON) -std=c99
CXXFLAGS += $(INC_DIRS) $(CFLAGS_CXXFLAGS_IN_COMMON) -std=c++11
 
LDFLAGS += $(CFLAGS_CXXFLAGS_IN_COMMON)
LDLIBS +=
 
SRC_FILES_C := $(wildcard *.c)
SRC_FILES_CXX := $(wildcard *.cpp)
 
#If there's no C++ files then use the C compiler to link
ifeq ($(SRC_FILES_CXX),)
LINKER = $(CC)
else
LINKER = $(CXX)
endif
 
OBJECTS += $(SRC_FILES_C:.c=.c.o) $(SRC_FILES_CXX:.cpp=.cpp.o)
 
DEPENDENCIES += $(OBJECTS:.o=.d)
 
.PHONY: all
all: $(PROGRAM) $(DEPENDENCIES)
 
#This rule runs the linker to combine object files into one executable binary file
$(PROGRAM): $(OBJECTS)
$(LINKER) $(LDFLAGS) $^ $(LDLIBS) -o $@
 
#This rule makes dependencies files for the source files
.PRECIOUS: %.c.d
%.c.d: %.c
$(CC) $(INC_DIRS) -MM -MT $(<:.c=.c.o) $< -MF $@
 
.PRECIOUS: %.cpp.d
%.cpp.d: %.cpp
$(CXX) $(INC_DIRS) -MM -MT $(<:.cpp=.cpp.o) $< -MF $@
 
#This rule compiles the source files to object files
%.c.o: %.c %.c.d
$(CC) $(CFLAGS) -o $@ -c $<
 
%.cpp.o: %.cpp %.cpp.d
$(CXX) $(CXXFLAGS) -o $@ -c $<
 
#This next line pulls in all the dependency files (if they exist, and it's not "make clean")
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPENDENCIES)
endif
 
.PHONY: clean
clean:
$(RM) $(DEPENDENCIES) $(OBJECTS) $(PROGRAM) $(OBJECTS:.o=*.expand)
 
#These next two rules to (un)install are only for Linux
 
#If DESTDIR is not set then set it
ifeq ($(DESTDIR),)
DESTDIR = /usr/bin
endif
 
.PHONY: install
install: $(PROGRAM)
cp $< $(DESTDIR)
 
.PHONY: uninstall
uninstall:
$(RM) $(DESTDIR)/$(PROGRAM)
Marcel Mueller <news.5.maazl@spamgourmet.org>: Jan 14 07:22PM +0100

Am 14.01.20 um 14:38 schrieb Frederick Gotham:
> A few months ago I posted about my generic Makefile that builds a C/C++ program from all the source files in the current directory. I've been using this Makefile for the past few months on loads of different programs (big and small) and it works well.
 
You probably should not reinvent the wheel.
There are several build utilities around. There is no need for another
one that works sometimes. If you want to be portable you cannot rely on
gcc neither on Gnu make. Other compilers and tool chains are common too.
 
For C/C++ cmake is a reasonable starting point. Although like any other
tool it has some drawbacks, but it supports plenty much of platforms and
tool sets, including make install.
 
 
Marcel
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Jan 14 07:35PM

On 14/01/2020 13:38, Frederick Gotham wrote:
 
> .PHONY: uninstall
> uninstall:
> $(RM) $(DESTDIR)/$(PROGRAM)
 
bleh.
 
CMake.
 
/Flibble
 
--
"Snakes didn't evolve, instead talking snakes with legs changed into snakes." - Rick C. Hodgin
 
"You won't burn in hell. But be nice anyway." – Ricky Gervais
 
"I see Atheists are fighting and killing each other again, over who doesn't believe in any God the most. Oh, no..wait.. that never happens." – Ricky Gervais
 
"Suppose it's all true, and you walk up to the pearly gates, and are confronted by God," Byrne asked on his show The Meaning of Life. "What will Stephen Fry say to him, her, or it?"
"I'd say, bone cancer in children? What's that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery that is not our fault. It's not right, it's utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates a world that is so full of injustice and pain. That's what I would say."
Paavo Helde <myfirstname@osa.pri.ee>: Jan 14 10:47PM +0200

On 14.01.2020 15:38, Frederick Gotham wrote:
 
> .PHONY: uninstall
> uninstall:
> $(RM) $(DESTDIR)/$(PROGRAM)
 
I agree with other responders. The above looks more like assembler or
PostScript code, i.e. not really something meant for humans to write.
And the result looks pretty non-portable and limited to a single type of
projects.
 
While I have done my share of makefile programming in the past I'm ready
to admit I never got it quite right; by looking at makefiles generated
by CMake I can now understand why.
 
So what's wrong with using CMake instead?
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jan 13 04:21PM -0800

On 1/12/2020 6:53 PM, James Kuyper wrote:
 
> This is a trivial problem to workaround. Why do you need o.b? For
> whatever purpose you need it, why couldn't you use o.o0.b or o.o1.b (it
> doesn't matter which one you choose - which is the whole point) instead?
 
Excellent point. Added it there when I quickly typed this code in.
Therefore, I do not have a solid answer. However, perhaps it had
something to do with thinking that o.b should map to o.o0.b and o.o1.b.
All are one and one is all type of union relationship here. My bad.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jan 13 04:27PM -0800

On 1/13/2020 8:57 AM, Tim Rentsch wrote:
> ... // presumably o1 is the active member
> }
 
> Does that all make sense?
 
Yes. I must of been thinking of some syntactic sugar wrt sticking the
base object in the union itself. As in, perform some function on o.o1
and read all of its "common" alterations from o.b. An out of many, one,
type of relationship. However, reading from o.o0.b, or o.o1.b provides
everything I need anyway for &(o.o0.b) == &(o.o1.b).
 
I added in the extraneous base in the union out of some sort of reflex
mixed with trying to just read from o.b.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jan 13 04:29PM -0800

On 1/13/2020 8:37 AM, Tim Rentsch wrote:
>> same address as union object::o1::base. Its all POD.
 
> I see you have gotten some further guidance on this matter.
> I will respond further to your posting downstream.
 
Thank you Tim. Indeed I have received some really interesting facts on
the matter. Thank you, and all.
James Kuyper <jameskuyper@alumni.caltech.edu>: Jan 13 09:47PM -0500

On 1/13/20 5:15 PM, Öö Tiib wrote:
 
> If a standard-layout class object has any non-static data members, its
> address is the same as the address of its first non-static data member.
> [class.mem]24
 
That's not what I'm looking for. That's a rule that allows you to reach
the conclusion that two objects are at the same address. I'm looking for
the rule who's existence is implied by your argument, which allows you
to take the fact that two struct members must be at the same address,
and from that fact conclude that they are corresponding members of the
common initial sequence of two struct types.
 
> data member is of type "base" are both addresses of object of
> type "base". Two standard layout objects of type "base" are
> layout compatible, aren't those?
 
True - but irrelevant. You've dropped the relevant code, but I'm going
to reinstate it in order to make it clear what I'm referring to.
 
On 1/2/20 6:39 PM, Chris M. Thomasson wrote:
> };
 
> int main() {
> object o;
 
I'm in perfect agreement that o.b, o.o0.b and o.o1.b all have the same
type, and therefore have layout-compatible types. I'm also in agreement
that all three have the same address. The fact that o.o0.b and o.01.b
have layout compatible types means that it's perfectly safe to write to
o.o0.b.p0, and read from o.o1.b.p0 - the value you read is guaranteed to
be the same as the the value that was written, because of 9.2p19.
 
However, no similar conclusion can be derived from the fact that o.b is
layout compatible with the other two objects, nor from the fact that it
has the same address as they do. If you feel otherwise, please cite the
rule that allows it.
 
The first point to note is that in order to apply 9.2p19, the two
structs being compared must be members of the union. So if you're
looking at o.b and o.o0.b, the struct types that you need to compare are
struct base and struct object_0. o.o0.b is not a member of the union -
it's a member of a member of the union, so it's type is not directly
relevant to the question of whether or not 9.2p19 applies.
 
The second point to note is that the common initial sequence of two
struct types A and B is an ordered list of pairs of members, each pair
containing one non-static data member of struct A, and one non-static
data member of struct B. The list must be in the same order as the
declarations of the members in each struct types, and the members of
each pair must have layout compatible types.
 
The only member of o.b is named "p0" and has the type "int". There are
two members of o.o0, named "b" and "p0", which have the types "struct
base" and "int" respectively. If you claim that struct base and struct
object_0 have a common initial sequence, then the first and only member
of that common initial sequence would have to be the first member of o.b
(which is o.b.p0) paired up with the first member of o.o0 (which is
o.o0.b). But o.b.p0 has the type "int", while o.o0.b has the type
"struct base". There's no rule that allows you to conclude that any
struct type is layout compatible with any scalar type.
 
Let me address that last point in more detail. 3.9p11 identifies three
ways that you can reach the conclusion that two types are layout-compatible:
 
1. The types cv1 T1 and cv2 T2 (where cv1 and cv2 are optionally empty
lists of type qualifiers) are compatible only if T1 and T2 are the same
type. But "int" and "struct base" are not the same type.
 
2. Two enumerations can be layout compatible if they have the same
underlying type (7.2p9). But neither "int" nor "struct base" is an
enumeration.
 
3. Two standard-layout class types can be layout compatible (9.2p17) if
they have the same number of non-static data members and each such
member of one struct type is layout-compatible with the corresponding
member of the other struct type. But "int" is not a class type, and
therefore, in particular, cannot qualify as a standard-layout class type.
"Öö Tiib" <ootiib@hot.ee>: Jan 13 11:44PM -0800

On Tuesday, 14 January 2020 04:47:42 UTC+2, James Kuyper wrote:
> layout compatible with the other two objects, nor from the fact that it
> has the same address as they do. If you feel otherwise, please cite the
> rule that allows it.
 
So o.b, o.o0.b and o.o1.b are all objects of same type at
same storage location but writing to one and reading from other
is still prohibited? There are no volatile or something like that
in play here, so I am expecting such prohibition to be explicit
in standard. Both Tim and you seem to say that first member of
those being an int somehow causes contradiction but the idea does
not shine thru into my thick skull. :(
 
 
James Kuyper <jameskuyper@alumni.caltech.edu>: Jan 14 08:26AM -0500

On 1/14/20 2:44 AM, Öö Tiib wrote:
> On Tuesday, 14 January 2020 04:47:42 UTC+2, James Kuyper wrote:
...>> On 1/2/20 6:39 PM, Chris M. Thomasson wrote:
> in standard. Both Tim and you seem to say that first member of
> those being an int somehow causes contradiction but the idea does
> not shine thru into my thick skull. :(
 
To put this in proper perspective, let's start by considering a single
variable.
 
The C++ standard says that "An instance of each object with automatic
storage duration (3.7.3) is associated with each entry into its
block. Such an object exists and retains its last-stored value during
the execution of the block and while the block is suspended (by a call
of a function or receipt of a signal)." (1.9p7).
 
I could not locate wording in the C++ standard that says the anything
comparable about objects with other storage durations - which surprises
me. I suspect that I've missed something. For comparison, the C standard
says "An object ... retains its last-stored value throughout its
lifetime." (C2011 6.2.4p4) without restricting that guarantee to objects
with any particular storage duration. For objects with automatic storage
duration, "during the execution of the block and while the block is
suspended" corresponds to the lifetime of that object, so the C and C++
standards agree for such objects.
 
Retaining their last-stored value is an essential feature of usable
variables. I'm going to go ahead on the assumption that C++ does
actually say this somewhere for other storage durations, and I just
missed it. Alternatively, you can assume that what I'm saying below only
applies to objects with automatic storage duration (which would render
objects with other storage durations essentially unusable).
 
Implementations of C++ typically store an object in particular locations
in RAM, but that memory location does not always contain the last-stored
value of that object. Often, the last-stored value currently resides
only in one or more registers somewhere. This is allowed by the as-if
rule. When the last-stored value of a variable is needed, it doesn't
matter whether the compiler retrieves that value from memory or from a
register, so long as the location that it retrieves it from does in fact
contain the last-stored value. It's up to the compiler to keep track of
where the last-stored value is currently stored, and so long as it does
so correctly, the as-if rule allows this.
I don't mean to imply that register/memory issues are the entire reason
for the rules I'm discussing. Transfers between memory and register are
allowed precisely because (and only insofar as) the C++ standard fails
to say anything to prevent it. I'm just using such issues as a simple,
easy-to-understand example of the kinds of things governed by these rules.
 
Here's the key point: the different members of a union are considered to
be distinct objects that just happen to be stored in the same location.
For example, given
 
union { int i; float f; }u;
 
an implementation can treat u.i and u.f as if they were distinct
variables, despite the fact that they sit in the same location in
memory. It can keep track of whether u.i is stored in the location
pointed at by &u.i, or in an integer register. It can keep track of
whether u.f is stored in the location pointed at by &u.f or in a
floating point register. However, since it's undefined behavior to read
a different member of a union than the one that was last written to, an
implementation is NOT required to coordinate transfers between u.i and a
register with transfers between u.f and a register. Therefore, if you
write to u.i, that written value might still be in a register at the
time that subsequent code retrieves u.f from memory. Alternatively, if
the value of u.i does get moved to memory, a read of u.f might retrieve
the value last stored in u.f, which is still in a register somewhere.
When more complex objects are in the union, such as objects of struct
type, the ways in which accesses to members of different structs can
interfere with each other get even more complicated.
 
This anarchy is the normal case for accesses to union members, but
9.2p19 provides an exception to this anarchy for the common initial
sequence of two struct types, so long as those struct types are members
of the same union. If you write a value to a member in the common
initial sequence using one of those two struct types, and read from the
corresponding member of the other struct type, the value read must match
the value written. An implementation is still free to store that value
either in the object itself, or in a register, but it must store and
retrieve that value from the correct location, regardless of which of
the two struct types is used to write it, and regardless of which of the
two struct types is used to read it.
 
Therefore, you're relying upon the guarantee provided by 9.2p19 in order
to perform such accesses. And the conditions for the applicability of
9.2p19 are not met by o.b.p0, for the reasons I gave above in my earlier
message. Since the common initial sequence is determined entirely by the
membership relationships and types of the relevant objects, and not by
their addresses, the fact that o.b.p0 and o.o0.b.p0 are stored in the
same location does not guarantee that 9.2p19 covers those two objects.
Tim Rentsch <tr.17687@z991.linuxsc.com>: Jan 14 07:05AM -0800

"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> writes:
 
[...]
 
> I added in the extraneous base in the union out of some sort of
> reflex mixed with trying to just read from o.b.
 
Maybe you were thinking of programming in C. In C there is often
benefit to have a "stub" type that serves mainly to differentiate
the "concrete" types. AFAICT in C++ there is not, except perhaps
as some sort of aid to the reader.
Tim Rentsch <tr.17687@z991.linuxsc.com>: Jan 14 07:30AM -0800

Tiib writes:
 
> On Monday, 13 January 2020 19:02:00 UTC+2, Tim Rentsch wrote:
 
[context: this code
 
struct base {
int p0;
};
 
struct object_0 {
base b;
int p0;
};
 
]
 
>> are not layout compatible. Do you agree or disagree?
 
> I disagree. The address of base is required to be address of int as
> well as first element of base so these are layout compatible.
 
In N4659, section 6.9 paragraph 11 defines the term 'layout
compatible'. The definition says (leaving out the cv's) that two
types T1 and T2 are layout compatible if
 
(a) T1 and T2 are the same type,
 
(b) T1 and T2 are layout-compatible enumerations, or
 
(c) T1 and T2 are layout-compatible standard-layout class types.
 
When T1 is 'int' and T2 is 'base' (aka 'struct base'), which of these
categories do you think applies?
"Öö Tiib" <ootiib@hot.ee>: Jan 14 09:11AM -0800

On Tuesday, 14 January 2020 17:30:46 UTC+2, Tim Rentsch wrote:
 
> (c) T1 and T2 are layout-compatible standard-layout class types.
 
> When T1 is 'int' and T2 is 'base' (aka 'struct base'), which of these
> categories do you think applies?
 
T1 is also 'base' so (a) applies.
Tim Rentsch <tr.17687@z991.linuxsc.com>: Jan 14 07:16AM -0800

Tiib writes:
 
> On Saturday, 11 January 2020 08:48:50 UTC+2, Tim Rentsch wrote:
 
[...]
 
> words are used by certain people to express something and so these
> words have that meaning. In C++ standard these words are not used
> to mean anything and so can not cause confusion with slang of C++.
 
When your aim is to communicate with people while speaking (or
writing) English, it's almost always better to use words in the
way that they are likely to be most commonly understood. Using
dictionaries is good for this purpose, precisely because it is
widely accepted (at least in English speaking cultures) that they
provide good and fairly reliably authoritative information. In
short, using dictionaries is good because everyone knows to
consult them.
"Öö Tiib" <ootiib@hot.ee>: Jan 14 08:55AM -0800

On Tuesday, 14 January 2020 17:16:57 UTC+2, Tim Rentsch wrote:
> provide good and fairly reliably authoritative information. In
> short, using dictionaries is good because everyone knows to
> consult them.
 
I usually do not communicate with purpose of using English.
However I checked couple dictionaries and figured out that
"bald" has roughly two meanings:
1: bare, barren, naked, hairless, having no covering.
2: simple, unadorned, blunt.
So I feel that "bald assertion" carries what I meant.
So it makes me unsure about what you complain.
Tim Rentsch <tr.17687@z991.linuxsc.com>: Jan 14 07:08AM -0800

Tiib writes:
 
> On Saturday, 11 January 2020 06:44:28 UTC+2, Tim Rentsch wrote:
 
[...]
 
> where usage of inline functions, templates or constants would
> be as simple but would not cause the issues existence of whose
> you dismiss.
 
That may be interesting but it doesn't address the question
I was asking.
"Öö Tiib" <ootiib@hot.ee>: Jan 14 08:42AM -0800

On Tuesday, 14 January 2020 17:08:45 UTC+2, Tim Rentsch wrote:
> > you dismiss.
 
> That may be interesting but it doesn't address the question
> I was asking.
 
Your question was "Why do C++ fans hate the C preprocessor so much?".
Paulo da Silva <p_s_d_a_s_i_l_v_a_ns@netcabo.pt>: Jan 14 01:04AM

Às 21:45 de 13/01/20, Jorgen Grahn escreveu:
> On Mon, 2020-01-13, Paulo da Silva wrote:
...
 
 
>> Sorry, I hadn't seen your answer when I posted.
 
> Come to think of it, I posted it only 20--30 minutes before you posted
> so I shouldn't have assumed you had.
 
Yes, I needed to leave the computer for a while when responding.
 
>> rest of the project.
 
> I must assume that means "it's at work, so I cannot disclose that
> information".
No, but this is a moderate sized project, not new, and I want to keep
those warnings, if there are members uninitialized, except for special
cases like this.
 
 
> I strongly dislike the first two -- they bring in C style thinking,
> and would happily and silently trash cur_dev if it ever got a real
> constructor.
So do I. That's the main reason why I asked for suggestions.
 
> But if you cannot make that decision, I think you should go to whoever
> makes those decisions and ask "well, how do you want me to handle this
> situation, then"?
Of course I could just ignore the warning, but I became curious on how
to "clean" just this one. I also like clean compilations.
 
Thanks.
Frederick Gotham <cauldwell.thomas@gmail.com>: Jan 14 12:34AM -0800

On Monday, January 13, 2020 at 6:53:28 PM UTC, Paulo da Silva wrote:
 
> Is there a way to tell the compiler that I don't want that member to be
> initialized?
 
> Thanks
 
 
You need to turn the warning off just for that one line.
 
You "push" the current compiler warning settings, you disable that one warning, you do your line of code, and then you "pop" all the warnings back the way they were.
 
Like this:
 
int main(void)
{
int i;
 
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wuninitialized"
int j = i + 5;
#pragma GCC diagnostic pop
 
return 0;
}
 
If you want a portable way of doing this, look for "Hedley":
 
https://nemequ.github.io/hedley/user-guide.html
Paulo da Silva <p_s_d_a_s_i_l_v_a_ns@netcabo.pt>: Jan 14 03:33PM

Às 08:34 de 14/01/20, Frederick Gotham escreveu:
> }
 
> If you want a portable way of doing this, look for "Hedley":
 
> https://nemequ.github.io/hedley/user-guide.html
 
This is worth seeing.
 
Thank you.
Bonita Montero <Bonita.Montero@gmail.com>: Jan 14 08:11AM +0100

I cppreference I found:
"A specialization of std::less for any pointer type yields a
strict total order, even if the built-in operator < does not. ..."
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Why should the < operator not gain a "strict total order" on
pointers?
Bonita Montero <Bonita.Montero@gmail.com>: Jan 14 08:33AM +0100

>                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> Why should the < operator not gain a "strict total order" on
> pointers?
 
Even segmented addressed pointers had a "strict total order".
Paavo Helde <myfirstname@osa.pri.ee>: Jan 14 12:14PM +0200

On 14.01.2020 9:33, Bonita Montero wrote:
>> Why should the < operator not gain a "strict total order" on
>> pointers?
 
> Even segmented addressed pointers had a "strict total order".
 
This is the zero overhead principle. Normalizing the segmented pointers
for strict total order comparison would take some CPU cycles and use
more memory. However, the whole point of segmented architectures is to
avoid this overhead when working inside a single segment. C and C++
standards have been carefully worded to support such architectures, so
that fast comparison can be used inside a single array where it matters
most.
 
A hypothetical C++ compiler supporting "strict total order" for '<'
operator would have to emit a more expensive comparison for '<' every
time it could not prove the pointers point to the same array, making the
same code run slower than in C. This was and is a big no-no, especially
in the past when optimizers were weak and segmented architectures were a
real thing.
Bonita Montero <Bonita.Montero@gmail.com>: Jan 14 02:22PM +0100

> A hypothetical C++ compiler supporting "strict total order" for '<'
> operator would have to emit a more expensive comparison for '<' every
> time it could not prove the pointers point to the same array, ...
 
That's not hypothetical but true for the ancient 808x- / 80286-compilers
depending on the chosen memory-model. Even the early MS Quick C compiler
has full blown pointer arithmetics for every pointer if you chose com-
pact, large or huge memory model. And even if you chose the small or
medium memory-model with one data-segment you usually address memory
outside the data-segment with pointers attributed as far or huge
which gives you the same comparison-semantics. And with huge you might
even address arrays spanning more than one segment if the data type
fits an even numbered times in a segment.
And most of that isn't specified in the language-standard but is com-
piler and platforms-specific.
Frederick Gotham <cauldwell.thomas@gmail.com>: Jan 14 02:25AM -0800

On Friday, January 10, 2020 at 3:06:23 PM UTC, Tim Rentsch wrote:
 
> > It should fail to compile with compilers that enforce good taste.
 
> So, not on any currently conforming C++ compiler, you mean?
 
 
I, too, tried logic on this argument here on this newsgroup. I found that logic failed. I might try rationale next.
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: