GCC is re-implementing in C++ and C discarded

J

Johannes Bauer

While that has been true for some toolchains, it's kind of not true any
more. There are .DATA , .TEXT and .BSS. The default is to put them into
RAM. If you write your own linker scripts, then you can
do what you like.
(yes, there's also the heap and the stack... )

That is precisely what I'm doing. The example was just abbreviating the
whole thing. Actually I use some implementation defined construct to
place the const struct IVT into its own section. That section then gets
relocated to the correct place by linker magic.
If it works in 'C' the chances are excellent that it will work in C++.
The problem he had above was the construct ".vec1 = 1234," - the
".vec1 = " part is not recognized in C++. C++ forces you to declare
const memory layouts in order.

Yes, and in this particular case it is incredibly annoying. Especially
when you have code that is portable across two devices (two interrupts,
same name, same setup, everything the same except their location in the
IVT). Since in my solution by calling them by name and including a
setup-file which specifies the CPU-specifics, it "just works". Entries
are at the correct location.

With C++ you'd have to maintain two different IVT files and have to look
that stuff up manually. And it are actually a *lot* of IRQs that these
devices offer. Pretty glad with the C solution for this one.

Best regards,
Johannes

--
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen
Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <[email protected]>
 
J

James Kuyper

Yes, when you comment out the whole point of the example, it works.

But the part that was commented out was pointless; if it was the point
of the example, the example had no point. Yes, I'm playing with words -
but it's also all literally true.
 
J

Johannes Bauer

???
The claim was that use of C was a necessity, not just a convenience. C
doesn't have constructors, and designated initializers are only a
convenience feature that don't do anything that can't already be done
using ordinary initializers - they just make it more convenient.

By that twisted logic, every Turing complete logic has the same feature
set, since they're all Turing complete. Every syntacitical primitive is
just "convenience".

Give me a break here. That's ridiciulous. Designated initializers are
something missing from C++ and they're something that are *actually*
incredibly useful, as I can demonstrate. Obviously, you can still get it
done somehow, but this is not the point: The point is finding an
solution which minimizes effort. This is possible in C, but in this
instance it is not with C++.

Best regards,
Johannes

--
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen
Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <[email protected]>
 
J

Johannes Bauer

But the part that was commented out was pointless; if it was the point
of the example, the example had no point. Yes, I'm playing with words -
but it's also all literally true.

Alright, then, since you do understand what I'm getting at but are
unwilling to recoginze the point, here's a more complete example.
Imagine there are 3 hardware platforms (these are about 10-20 in
reality) each which have 10 IRQ vectors (these at least 100 in reality):

hw1.h:
struct ivtlayout {
int vec1;
int vec2;
int vec3;
int vec6;
int vec4;
int vec7;
int vec9;
int vec5;
int vec8;
int vec0;
};

hw2.h:
struct ivtlayout {
int vec4;
int vec2;
int vec5;
int vec8;
int vec1;
int vec3;
int vec9;
int vec0;
int vec6;
int vec7;
};

hw3.h:
struct ivtlayout {
int vec7;
int vec6;
int vec9;
int vec8;
int vec4;
int vec1;
int vec3;
int vec0;
int vec5;
int vec2;
};


Now you want to include for each version a IVT which specifies a value
for vector 8. C solution:

struct ivtlayout ivt = {
.vec8 = 1234,
};

I'll leave the C++ solution as an excersise to you. Hopefully you'll see
the point now.

Best regards,
Johannes


--
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen
Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <[email protected]>
 
J

James Kuyper

Please refer to this discussion a year back about exactly that issue
(the thread was called "C vs. C++: non-trivial designated initializers
not supported"):

https://groups.google.com/forum/?hl=en&fromgroups=#!topic/comp.lang.c++/HeWVpymftTg

The phrase "pre-initialized structs" appears to refer to structs that
are initialized at the point of definition, rather than being
initialized after being defined. Assuming that this is what you mean,
there's no problem with pre-initializing structs in C++. You can't use
designated initializers to do so, which is what that thread was about,
but you can use ordinary initializers. This is no different from C90.
 
J

Johannes Bauer

The phrase "pre-initialized structs" appears to refer to structs that
are initialized at the point of definition, rather than being
initialized after being defined. Assuming that this is what you mean,
there's no problem with pre-initializing structs in C++. You can't use
designated initializers to do so, which is what that thread was about,
but you can use ordinary initializers. This is no different from C90.

Yes, it does. Which is also why C90 is out of the question (equally
stupid "solution" as the C++ one) and which is why I compiled my example
with -std=c99. Maintaing the mess (I kind of hint to the actual problem,
these are obviously just overly simplified examples) is just not
something that I want to do manually, and it is very error-prone. With
designated initializers there is a nice solution available in C99, but
not in C++11.

Best regards,
Johannes

--
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen
Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <[email protected]>
 
J

James Kuyper

James Kuyper wrote: ....

While that has been true for some toolchains, it's kind of not true any
more. There are .DATA , .TEXT and .BSS. The default is to put them into
RAM. If you write your own linker scripts, then you can
do what you like.
(yes, there's also the heap and the stack... )

For additional partitions, you have to use ... pragmas are other domain
dependent extensions.

You're probably right - for a particular set of platforms (probably a
very large and popular set of platforms), but it's not universally true.
You could probably identify that set better than I can - it would have
been completely inappropriate for me to worry about such details in any
program I've written since 1995.

....
If it works in 'C' the chances are excellent that it will work in C++.
The problem he had above was the construct ".vec1 = 1234," - the
".vec1 = " part is not recognized in C++. C++ forces you to declare
const memory layouts in order.

It may be more convenient to be able to initialize them in arbitrary
order, but it's certainly not a necessity, as originally claimed.
 
J

Johannes Bauer

Johannes Bauer wrote:

Sounds like 'C' is the better solution in this case.

Thank you ;-)

That is actually what I went for. Although it would have been more
consistent (most of the rest of the code, including the HW abstraction
library is C++), in this particular case, the solution using C was so
much more elegant, that it was implemented.

Best regards,
Johannes


--
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen
Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <[email protected]>
 
L

Les Cargill

Johannes said:
Please refer to this discussion a year back about exactly that issue
(the thread was called "C vs. C++: non-trivial designated initializers
not supported"):

https://groups.google.com/forum/?hl=en&fromgroups=#!topic/comp.lang.c++/HeWVpymftTg

Best regards,
Johannes


I stand by my statement. Indeed, I inlined some working code.
the problem continues to be that somebody is confused by
the lack of support for designated intializers. You can still have
fully initialized structs/classes; it is just that not all toolchains
support designated intializers.
 
L

Les Cargill

Johannes Bauer wrote:
With C++ you'd have to maintain two different IVT files and have to look
that stuff up manually. And it are actually a *lot* of IRQs that these
devices offer. Pretty glad with the C solution for this one.

Sounds like 'C' is the better solution in this case.
 
J

Johannes Bauer

I stand by my statement. Indeed, I inlined some working code.
the problem continues to be that somebody is confused by
the lack of support for designated intializers. You can still have
fully initialized structs/classes; it is just that not all toolchains
support designated intializers.

Well, any conforming C99 *must* support designated initializers.

And, maybe I should've worded it wrong: Obviously, a solution is
possible in C++, but not an elegant one. In this particular case, the
C++ solution is so much worse that I went for C.

Best regards,
Johannes

--
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen
Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <[email protected]>
 
A

Anonymous

Steven G. Kargl said:
On 8/24/2012 5:15 AM, Nick Keighley wrote:
[...]
this whole conversation strikes me as bizzare. A kind of level
confusion. It reminds of one of my collegues who came out with "C++ is
upwards compatible with C because it is implemented in C" and couldn't
see what was wrong with that statement.

"Assembler must be upwards compatible with C, because 'as' is written in C."

"FORTRAN must be upwards compatible with C, because gnu FORTRAN is written
in C." (I think.)

The name of the language is "Fortran". It's been Fortran since
the Fortran 1990 standard.

So what? FORTRAN is no less FORTRAN now then it was then. Perhaps he was
talking about gnu's shitty F77 compiler.

Just because people born after 1990 don't know an acronym from a proper name
doesn't change reality.
The GNU Fortran frontend is written in C. Some of the GNU
Fortran runtime is written in m4. The m4 files when processed
generates Fortran code. The Fortran code is then compiled by
GNU Fortran.

OMG no. You didn't just write "Some of the GNU Fortran runtime is written in
m4."

Oh yes you did. Just another reason not to use gnu's shitty toolchain. How
do you motherfuckers sleep at night?

Goodbye to gcc's grotesque bloat and "i was drinking that night" design,
goodbye to Stallmanesque Marxism, hello clang/LLVM!
 
J

Jorgen Grahn

Jorgen Grahn:
C++ is a superset of C (pedants, attack !!!). So if you write C rather than
C++ you've necessarily rejected C++. The only exception is when you're
developing for tiny embedded systems that don't come with a C++ compiler.

Why would you do that? Basically to make code more reusable, and to reduce
dependencies between source files. If my binary image library was in C++,
fr example, then a "binary image" would be an "object".

C++ isn't Java; nothing forces you to design everything as classes.

/Jorgen
 
S

Steven G. Kargl

Steven G. Kargl said:
On 8/24/2012 5:15 AM, Nick Keighley wrote:
[...]
this whole conversation strikes me as bizzare. A kind of level
confusion. It reminds of one of my collegues who came out with "C++ is
upwards compatible with C because it is implemented in C" and couldn't
see what was wrong with that statement.

"Assembler must be upwards compatible with C, because 'as' is written in C."

"FORTRAN must be upwards compatible with C, because gnu FORTRAN is written
in C." (I think.)

The name of the language is "Fortran". It's been Fortran since
the Fortran 1990 standard.

So what? FORTRAN is no less FORTRAN now then it was then. Perhaps he was
talking about gnu's shitty F77 compiler.

Except even your spelling in all caps is incorrect. If you take that time
to look at the Fortran standards, you find that the 'ORTRAN' is written in
a small cap font. After 25 years, is it asking to much to spell the
name of the language correctly?

GNU GCC does not have a shitty F77 compiler. g77 was deprecated years ago.
Since April 20, 2005, the Fortran compiler in GCC is gfortran, and for the
last few years gfortran has been competitive with all commercial available
Fortran compilers.
OMG no. You didn't just write "Some of the GNU Fortran runtime is written in
m4."

Yes, I did. But, you failed to read the next sentence. When you build
GCC with gfortran support, the m4 files are processed to generated some
Fortran code for the runtime library. That Fortran code is then compiled
by the just built Fortran compiler.

http://gcc.gnu.org/viewcvs/trunk/libgfortran/m4/

Your response is a classic example of someone who does not understand
the principle of using the right tool to get a job done.
Oh yes you did. Just another reason not to use gnu's shitty toolchain. How
do you motherfuckers sleep at night?

I sleep quite nicely.
Goodbye to gcc's grotesque bloat and "i was drinking that night" design,
goodbye to Stallmanesque Marxism, hello clang/LLVM!

Have you tried compiling any Fortran code with LLVM? LLVM does not have
its own Fortran compiler. It actually uses gfortran.

http://llvm.org/Features.html

"Front-ends for C, C++, Objective-C, Fortran, etc based on the GCC 4.2 parsers."

I can assure you that GCC 4.2.x's Fortran parser is fairly bad compared to
any of the newer versions.
 
K

Keith Thompson

Johannes Bauer said:
Well, any conforming C99 *must* support designated initializers.

And, maybe I should've worded it wrong: Obviously, a solution is
possible in C++, but not an elegant one. In this particular case, the
C++ solution is so much worse that I went for C.

Yes you worded it incorrectly. The problem is that your original
statement was about "pre-initialized structures" (which both C and
C++ have always supported), when what you *meant* was designated
initializers (which are supported in C starting with C99, but are not
supported in C++). Either using the right terminology *or* showing
sample code would have shortened this discussion considerably.
 
J

Jens Gustedt

Am 25.08.2012 21:23, schrieb James Kuyper:
???
The claim was that use of C was a necessity, not just a convenience. C
doesn't have constructors, and designated initializers are only a
convenience feature that don't do anything that can't already be done
using ordinary initializers - they just make it more convenient.

How would you do

unsigned char errVector[] = { [EINVAL] = true, [ERANGE] = true, };
enum { maxNeeded = sizeof(errVector), };

in C++ ?
???
A compound literal doesn't do any thing that can't be done with an
explicitly declared and named temporary object. Again, it's just a
convenience feature.

E.g you can't easily declare named temporaries in function-like
macros, and you can't easily protect named temporaries from accidental
use elsewhere in your code.

You can easily use anonymous temporaries in both languages for
that, but not with a common syntax.

Convenience is all that higher programming languages bring, no?
- no consistent way of passing dynamically sizes multi-dimensional
arrays to functions

???
int func (double *array, rows, cols)
{
// to access column c of row r:
array[r*cols + c]

VLAs are also just a convenience feature - the don't do anything that
can't be done less conveniently by other methods.

sizeof *array is a very convenient feature, and much less error prone
than copying the size expression all over your code.

Well again, yes for convenience I can explicitly declare a variable
that holds the size of *array, invent a naming convention for such a
thing as sizeof_array or so. I prefer to have a language (or library)
feature for that. Both C and C++ provide that feature but with
completely different syntax.
It might just be jealousy on my part - I've never been paid to program
in an environment where I was permitted to use either designated
initializers or VLAs; I've regretted having to work within those
restrictions, but never had any trouble working around them, so the
claim that a lack of support for those features renders C++ unusable
strikes me as quite laughable.

Have your laugh, I was not saying that. I was saying that the
intersection of those two languages is not very convenient to use. C++
has its own features that replaces them, more or less. (For designated
initializers there is not really a replacement, since C++ always
forces you to initialize in declaration order.)
Could you explain the relevant differences? There are things prohibited
in C++ unions that aren't even meaningful in C unions, but I'm not aware
of anything that C unions allow you to do that couldn't also be done in
C++. I'm willing to believe that I might have missed something, but you
need to be more specific.

AFAIK C++ got stuck with the initial wording that has been corrected
for C. In C++ reading another member that was written to is UB. In C
it is perfectly valid unless you happen to encounter a trap
representation for the read-type. Type punning is basically what
unions are made for in C. If you use unions for type punning the
compiler can arbitrarily decide to throw up on you, since this is UB,
anyhow.
There are significant subtle differences between the two languages with
respect to inlining.

subtle? I don't think that there is a valid use of that feature in the
intersection of C and C++ that covers all use cases. Either you may
encounter multiple symbols or the day you compile for debugging a
symbol is missing.
However, the supposed "necessity" of programming in
C as a result of those differences would be much clearer with a
sufficiently specific example.

I didn't say that there is necessity. I said that there are strong
forces that push you to chose a side.

Jens
 
J

Jens Gustedt

Am 26.08.2012 02:19, schrieb Jens Gustedt:
If you use unions for type punning the
compiler can arbitrarily decide to throw up on you, since this is UB,
anyhow.

This sentence is missing a prefix, sorry: In C++, if you use unions ...

(It is far too late here.)

Jens
 
K

Keith Thompson

Johannes Bauer said:
*sigh* Obviously, yes. But that's not the point. The point is being able
to tell what vectors you want to use and not need to search through a
list of 98 vectors and hit the correct array position (which is, quite
frankly, incredibly inconvenient).

I understand your point now, but it was not at all clear from your
earlier messages.

[...]
 
K

Keith Thompson

Jens Gustedt said:
Am 25.08.2012 21:23, schrieb James Kuyper: [...]
???
The claim was that use of C was a necessity, not just a convenience. C
doesn't have constructors, and designated initializers are only a
convenience feature that don't do anything that can't already be done
using ordinary initializers - they just make it more convenient.

How would you do

unsigned char errVector[] = { [EINVAL] = true, [ERANGE] = true, };
enum { maxNeeded = sizeof(errVector), };

in C++ ?

Probably something like:

unsigned char errVector[] = { };
enum { maxNeeded = sizeof(errVector), };

...

errVector[EINVAL] = true;
errVector[ERANGE] = true;

And depending on the context, the assignments might go into a
constructor, which avoids the possibility of forgetting to call it.

(This isn't to suggest that designated initializers aren't often
a great convenience, of course.)
 
J

Jens Gustedt

Am 26.08.2012 03:02, schrieb Keith Thompson:
Jens Gustedt said:
How would you do

unsigned char errVector[] = { [EINVAL] = true, [ERANGE] = true, };
enum { maxNeeded = sizeof(errVector), };

in C++ ?

I should have added a static for the vector, or insist that this is
file scope to make my point clearer, sorry.
Probably something like:

unsigned char errVector[] = { };

I don't think that this is valid C++. You have to have a size for the
vector if you have an initialization don't you?
enum { maxNeeded = sizeof(errVector), };

Hm, the sizeof operator isn't well defined here
errVector[EINVAL] = true;
errVector[ERANGE] = true;

These are statements and not initializations and thus limited to block
scope. The version with the designated initializers is compile time.
And depending on the context, the assignments might go into a
constructor, which avoids the possibility of forgetting to call it.

Well first of all arrays don't have constructors, so you'd have to
wrap the array in a struct. And so you would declare a type for just
the one instance of an array that you need?

Then struct members have to have a size that is determined at compile
time, so you'd have to apply a complicated max function for EINVAL and
ERANGE (and whatever other constants you are interested in.).

Then these statements would go into the executable (function) part of
the constructor, not in the initializer list. So your array-struct
would be runtime initialized.

The "real" C++ to achieve something equivalent (compile time
determination of an array size depending on perhaps lengthy list of
constants) would probably use some complicated templates to do meta
programming. Something like

MaxOf< EINVAL, ERANGE, /* other constants go here */ >::val

(probably there is something like this in C++ already, my C++ is a bit
rusty)

So this is something that is feasible in both languages, but with
completely different syntax.
(This isn't to suggest that designated initializers aren't often
a great convenience, of course.)

Well higher level programming languages are for convenience, aren't
they?

And it is not only convenience, it is also for maintainability,
verifiability and so.

Jens
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,079
Messages
2,570,574
Members
47,205
Latest member
ElwoodDurh

Latest Threads

Top