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

M

Malcolm McLean

בת×ריך ×™×•× ×¨×שון, 26 ב×וגוסט 2012 00:13:04 UTC+1, מ×ת Jorgen Grahn:
C++ isn't Java; nothing forces you to design everything as classes.
No, but people expect a C++ binary image library to work on binary image
objects. They expect something like a virtual base class they can then over-ride
to use packed bits.
If this isn't provided there's no real point in the library being in C++
 
K

Keith Thompson

Jens Gustedt said:
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?
Right.
enum { maxNeeded = sizeof(errVector), };

Hm, the sizeof operator isn't well defined here

And that's the point I missed. In your C version, the length of
errVector depends on the values of EINVAL and ERANGE; specifically, it's
`max(EINVAL, ERANGE) + 1` (given the obvious definition of `max()`).
It's not straightforwardly translatable to C++.

Yeah, I goofed.

Just curious: was your example contrived to demonstrate the point, or is
it based on something in real code?
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.
Yes.
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?

Maybe. Or maybe the C++ program would be structured in a way that the
initialization would naturally be inside a class/struct anyway.
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.

Right, but how important is that? As long as you have a mechanism to
ensure that the code is executed before the values are needed, and it's
only executed once, it shouldn't matter a whole lot. (Or maybe it does
matter for small embedded systems. Hmm.)

[snip]
 
J

Johannes Bauer

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.

You are correct here. I'll definitely remember this next time and
express myself more clearly.

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

Jorgen Grahn

???????????? ?????? ??????????, 26 ?????????????? 2012 00:13:04 UTC+1, ?????? Jorgen Grahn:
No, but people expect a C++ binary image library to work on binary image
objects. They expect something like a virtual base class they can then over-ride
to use packed bits.

I don't think they do. For one thing, many are reluctant to use
run-time polymorphism for tiny things like pixels, because of the
(at least percieved) performance penalty of millions of virtual calls
versus inlined straight function calls.

(Not that I advocate writing general-purpose libraries with C++-only
interfaces. A C interface makes much more sense for various reasons.)
If this isn't provided there's no real point in the library being in C++

That does not make sense. Run-time polymorphism is just /one/
language feature, and not the most important one.

/Jorgen
 
J

Jens Gustedt

Am 26.08.2012 11:04, schrieb Keith Thompson:
And that's the point I missed. In your C version, the length of
errVector depends on the values of EINVAL and ERANGE; specifically, it's
`max(EINVAL, ERANGE) + 1` (given the obvious definition of `max()`).
It's not straightforwardly translatable to C++.

Yeah, I goofed.

Just curious: was your example contrived to demonstrate the point, or is
it based on something in real code?

yes, kind of. In P99 I use some sort of table that if you boil it down
amounts to something like

char const*const errNames[] = {

#ifdef ERANGE
[ERANGE] = "ERANGE",
#endif
#ifdef EINVAL
[EINVAL] = "EINVAL",
#endif

/* etc for all the EXXX codes that I have heard of */

};

Maybe. Or maybe the C++ program would be structured in a way that the
initialization would naturally be inside a class/struct anyway.
maybe


Right, but how important is that? As long as you have a mechanism to
ensure that the code is executed before the values are needed, and it's
only executed once, it shouldn't matter a whole lot. (Or maybe it does
matter for small embedded systems. Hmm.)

It does matter for initialization ordering. Forcing initializers for
static objects to be executed in a prescribed order is really a
pain. I once designed such a thing, don't want to do it again.

In the example above, if I'd have any other initializer that depends
on that table of error strings, e.g its size, I am screwed.

An then I simply don't like things that can be checked and done at
compile time (and can thus be properly diagnosed by the compiler) do
be delayed to runtime.

Jens
 
R

Rui Maciel

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

A class isn't the same thing as an object, and with C++, even if you don't
employ a single class anywhere in your code, you are still forced to deal
with objects extensively.


Rui Maciel
 
J

Jorgen Grahn

A class isn't the same thing as an object,

He meant a class though: he went on to talk about abstract base
classes and so on.
and with C++, even if you don't
employ a single class anywhere in your code, you are still forced to deal
with objects extensively.

Not sure what you mean, although it sounds scary. But I'm not
strictly forced to do anything I don't already do in C.

/Jorgen
 
K

Keith Thompson

Rui Maciel said:
A class isn't the same thing as an object, and with C++, even if you don't
employ a single class anywhere in your code, you are still forced to deal
with objects extensively.

There is an unfortunate ambiguity in the word "object". The C++
standard's definition of the word, "An *object* is a region of
storage" ([intro.object], 1.8) is quite similar to the C standard's
definition, a "region of data storage in the execution environment,
the contents of which can represent values" (3.15).

But the word is commonly used in the context of "object-oriented
programming", OOP, to prefer to a more specific concept (which I
won't try to define here). It seems clear enough that Malcolm was
using the latter meaning.

Or did you mean something else?
 
L

lovecreatesbeauty

Even so, the existence of a C++ implementation that generates C code
doesn't imply anything about upwards compatibility. A C program
that uses `new` as an identifier is still an invalid C++ program.

Even their main function aren't compatible, how could they be compatible then?
 
K

Keith Thompson

lovecreatesbeauty said:
Even their main function aren't compatible, how could they be
compatible then?

Huh?

int main(void) { }

is perfectly valid in both C and C++, as is

int main(int argc, char *argv[]) { }

C++ adopted the "(void)" syntax specifically to maintain compatibility
with C.

Even the preferred C++ form:

int main() { }

, though there's some question about whether it's completely valid in C,
is accepted without complaint by most or all C compilers.
 
A

Andrew Smallshaw

Q: If it's more likely that I can get a job with language X, but getting a
job with language Y pays more, which language should I study?

Good point. Another would be the longevity of the language. Five
or ten years ago there were any number of VB programming jobs out
there typically offering salaries not much more than what an average
network technician can command. I've no concrete evidence to back
this up but my impression is that the number of adverts has dropped
at least an order of magnitude from its peak. PHP seems to be the
current flavour of the month.
 
L

lovecreatesbeauty

lovecreatesbeauty said:
]
Even so, the existence of a C++ implementation that generates C code
doesn't imply anything about upwards compatibility. A C program
that uses `new` as an identifier is still an invalid C++ program.
Even their main function aren't compatible, how could they be
compatible then?

int main(void) { }

is perfectly valid in both C and C++, as is

int main(int argc, char *argv[]) { }

C++ adopted the "(void)" syntax specifically to maintain compatibility
with C.

Even the preferred C++ form:

int main() { }

, though there's some question about whether it's completely valid in C,
is accepted without complaint by most or all C compilers.

I saw some C++ code like :)

void main()
{
/*...*/
}
 
J

James Kuyper

....
I saw some C++ code like :)

void main()
{
/*...*/
}

Well, I saw some C code like that too. Both languages define two
specific ways of defining main() that are guaranteed supported by every
hosted conforming implementation, this isn't one of them (C:5.1.2.2.1p1,
C++:3.6.1p2). Both languages explicitly allow an implementation to
accept additional forms, and many popular compilers for each language
will accept this form. Both standards fail to describe what happens if
you try to use a form not supported by your implementation, so the
behavior when you do so is undefined by reason of the absence of a
definition. (C:4p6, C++:1.3.13p3).

I don't see any relevant differences between the two languages in this
regard. Could you explain more fully how this constitutes an example of
incompatibility between C and C++?
 
L

lovecreatesbeauty

Well, I saw some C code like that too. Both languages define two

specific ways of defining main() that are guaranteed supported by every

hosted conforming implementation, this isn't one of them (C:5.1.2.2.1p1,

C++:3.6.1p2). Both languages explicitly allow an implementation to

accept additional forms, and many popular compilers for each language

will accept this form. Both standards fail to describe what happens if

you try to use a form not supported by your implementation, so the

behavior when you do so is undefined by reason of the absence of a

definition. (C:4p6, C++:1.3.13p3).

Hi James,

Thanks for reading.

I'm dumb. I meant in my previous message the following is valid C++ but illegal C.

int main() { /* ... */ }

What I hate about C++ is that it changes the C then adds extra features.

Objective-C just adds some other messaging features on C, and it leaves C unchanged. Its messaging parts are ugly though.

If the latest C11 paperwork had enriched the C library with more general data structures like list, queue, stack and common and algorithms on them like sort, search, that would be enough.
 
V

Vincenzo Mercuri

On 27/08/2012 16:36, lovecreatesbeauty wrote:
[..]
If the latest C11 paperwork had enriched the C library with more general data structures like list, queue, stack and common and algorithms on them like sort, search, that would be enough.

Then you should program in C++. If you need those extra features in the
C language you need C++. Demanding the Standard to make such a huge
change to the language is just nonsensical (to me).
 
J

James Kuyper

On 08/27/2012 10:36 AM, lovecreatesbeauty wrote:
....
... I meant in my previous message the following is valid C++ but illegal C.

int main() { /* ... */ }

What gives you that impression? What rule do you think it breaks?
 
J

Jens Gustedt

Am 27.08.2012 16:36, schrieb lovecreatesbeauty:
I'm dumb. I meant in my previous message the following is valid C++ but illegal C.

int main() { /* ... */ }

That is not so clear that it is illegal in C. The rules for
definitions of functions are more relaxed than those for pure
declarations. An empty list in a definition means that the function
doesn't receive any arguments, which is in accordance with one of the
two prototypes that are foreseen for main.

int foo(void);

and

int foo() { /* ... */ }

are compatible, I think.

So there is not really a problem here.

Jens
 
V

Vincenzo Mercuri

On 08/27/2012 10:36 AM, lovecreatesbeauty wrote:
...

What gives you that impression? What rule do you think it breaks?

I think it is implementation-defined whether it is supported or not,
even though almost all the implementations do support it. But I'd say
that it is not the "most portable" way to define main.
 
J

James Kuyper

I think it is implementation-defined whether it is supported or not,

Citation, please?
even though almost all the implementations do support it. But I'd say
that it is not the "most portable" way to define main.

The standard describes two ways of defining main(), and requires every
conforming implementation of C to support any definition of main
equivalent to one of those two ways. This form is not the same as either
one of those, but it is equivalent to the first of those two ways. The
same is true of the C++ standard. Therefore, I'd expect it to be
extremely portable. What gives you doubts on the matter?
 

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