473,387 Members | 3,750 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Compiled C vs C++

Hi, since I've done a bit of Java recently, I'm thinking of using some
C++ instead of C, just because the "class" syntax is looking more
convenient now.

One thing that makes me wonder is C++ code size though. I've heard that
C++ is supposed to be just a souped up C that makes you "pay as you go",
and I don't intend to go anywhere far. But a small toy class I wrote
generated much more code than the equivalent C struct, when instantiated
in a test main().

The C code did just what it was supposed to: malloc, fill some struct
fields and return. The C++ code generated two identical (!) constructor
functions that did about what the C one did. The calling code - of
course! - only called one of them, because on the syntax level there was
only one constructor. In addition, some kind of structure was generated
(I assume, the class), even though I don't have anything virtual, and I
don't see where code like I'm planning to write would ever need access
to the class structure.

So my question would be: why are there two constructors when I only
wrote one (even in the final, linked executable)? What/why is the funny
structure in the code? (compiler is GCC/G++ 4.0, but I'm sure 3.x isn't
much different/better)

I'm sure this is something of a FAQ (though Google didn't turn up any
really useful answer), so feel free to direct me to past posts.

Thanks,
Ulrich
May 23 '06 #1
14 1604
Ulrich Hobelmann wrote:

[...]

.... But a small toy class I wrote
generated much more code than the equivalent C struct, when instantiated
in a test main().


It would probably help to see the C++ code and C code you wrote,
including class equivalent C struct and main ()function. It might also
help to see the options (if any), you passed to the compiler.

regards
Andy Little

May 23 '06 #2
Ulrich Hobelmann wrote:
Hi, since I've done a bit of Java recently, I'm thinking of using some
C++ instead of C, just because the "class" syntax is looking more
convenient now.

One thing that makes me wonder is C++ code size though. I've heard that
C++ is supposed to be just a souped up C that makes you "pay as you go",
and I don't intend to go anywhere far.
What do *you* mean by "pay as you go"?
But a small toy class I wrote
generated much more code than the equivalent C struct, when instantiated
in a test main().

The C code did just what it was supposed to: malloc, fill some struct
fields and return. The C++ code generated two identical (!) constructor
functions that did about what the C one did. The calling code - of
course! - only called one of them, because on the syntax level there was
only one constructor. In addition, some kind of structure was generated
(I assume, the class), even though I don't have anything virtual, and I
don't see where code like I'm planning to write would ever need access
to the class structure.
How do you know it generated two identical constructors? Because you
looked at the generated assembly? If it did generate a function that
you don't use (which seems more like a bug or inefficiency in your
compiler rather than a problem with the language as defined in the C++
standard), any linker since the 1970s will strip them from the final
executable. Likewise, where did you draw your information about the
mysterious structure that the compiler generated?
So my question would be: why are there two constructors when I only
wrote one (even in the final, linked executable)? What/why is the funny
structure in the code? (compiler is GCC/G++ 4.0, but I'm sure 3.x isn't
much different/better)

I'm sure this is something of a FAQ (though Google didn't turn up any
really useful answer), so feel free to direct me to past posts.


As already requested, please post your code for both the comparable C
program and the C++ program. That will help us get to the bottom of
this.

Cheers! --M

May 23 '06 #3
kwikius wrote:
Ulrich Hobelmann wrote:
[..] It might also
help to see the options (if any), you passed to the compiler.


Not really. Compiler options discussions belong to the newsgroups
decidated to those compilers. Thanks for keeping this forum on topic.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
May 23 '06 #4
mlimber wrote:
What do *you* mean by "pay as you go"?
That - as IIRC mentioned in Bruce Eckel's Book - I can use a class as a
struct; that a (non-virtual) function in the struct will be called as
efficiently as a C function, because it is fully, statically known at
compile-time. If everything is there, and I don't use more advanced
features, I don't see why the code should be different from C.

Interestingly so far it seems as if I could get *more* efficient code by
writing my own C++ to C compiler (remember the very first C++ compiler?)
than by using something as high-tech as GCC 4.
How do you know it generated two identical constructors? Because you
looked at the generated assembly? If it did generate a function that
you don't use (which seems more like a bug or inefficiency in your
compiler rather than a problem with the language as defined in the C++
standard), any linker since the 1970s will strip them from the final
executable. Likewise, where did you draw your information about the
mysterious structure that the compiler generated?
They were both in the assembler output (c++ -O2 -S) and in the final
executable, as I said. The source only has one constructor (see below),
but the translation has two. I can't even *guess* how any compiler
would get the idea of doing something like this...
As already requested, please post your code for both the comparable C
program and the C++ program. That will help us get to the bottom of
this.


Sure, here goes:

take something like
class Foo
{
public:
Foo(int n);
private:
int foo;
};

Foo::Foo(int n)
{
foo = n;
}

Clearly this could be done in C by declaring Foo a struct with one
member, and by either allocating it on the stack, or by mallocing it and
calling some init-function (i.e. constructor), like void initFoo(Foo *
f, int n);. That's what I'm expecting C++ to do as well, as I don't use
other features.

The output (PPC, trimmed):
__ZN3FooC2Ei:
LFB3:
stw r4,0(r3)
blr
LFE3:
.align 2
.globl __ZN3FooC1Ei
__ZN3FooC1Ei:
LFB4:
stw r4,0(r3)
blr

I.e. there are two constructors, and if I use one, AFAIK only one (the
one with the '1' in the name) is used. In this case it's just a few
bytes, but I'm wondering about the general case.
May 23 '06 #5
> I.e. there are two constructors, and if I use one, AFAIK only one (the
one with the '1' in the name) is used. In this case it's just a few
bytes, but I'm wondering about the general case.


just a guess.. isn't one of them copy-constructor that compiler
generates for you if you don't provide one?

May 23 '06 #6
Hello

Ulrich Hobelmann wrote:
mlimber wrote:
What do *you* mean by "pay as you go"?
That - as IIRC mentioned in Bruce Eckel's Book - I can use a class as
a struct; that a (non-virtual) function in the struct will be called
as efficiently as a C function, because it is fully, statically known
at
compile-time. If everything is there, and I don't use more advanced
features, I don't see why the code should be different from C.


At what price on the C side? See below.

Interestingly so far it seems as if I could get *more* efficient code
by writing my own C++ to C compiler (remember the very first C++
compiler?) than by using something as high-tech as GCC 4.
Try some real world sized examples. Try to support all features C++
offers, e.g. templates, exceptions, inheritance, overloading. Anything
else is comparing apples and oranges.

Taking the higher abstraction C++ offers out of consideration, it is
sure that C++ will have a few overheads at places a C programmer could
easily have done better. In the past the trend was more towards
improving speed than code size.
They were both in the assembler output (c++ -O2 -S) and in the final
executable, as I said. The source only has one constructor (see
below),
but the translation has two. I can't even *guess* how any compiler
would get the idea of doing something like this...
If you want to program against binary code you need an ABI (application
binary interface), defining what can be expected from binary code. If
some implementation detail requires two variants of a constructor to be
available, which in general are different, then both variants will be
produced so they are available at link time. Probably they will be
produced consistently for all classes, because it is an ABI.
As already requested, please post your code for both the comparable C
program and the C++ program. That will help us get to the bottom of
this.
I.e. there are two constructors, and if I use one, AFAIK only one (the
one with the '1' in the name) is used. In this case it's just a few
bytes, but I'm wondering about the general case.


Then try the general case, find an example, where the other variant is
called. AFAIK gcc needs the second to implement inheritance, and other
C++ compilers are similar. After 20+ years there should be agreement on
the best way to implement something that basic.

Just in the case it helps, I think on some platforms there are
possibilities to remove unused code from the final binary at link time.
Bernd Strieder

May 23 '06 #7
Bernd Strieder wrote:
Try some real world sized examples. Try to support all features C++
offers, e.g. templates, exceptions, inheritance, overloading. Anything
else is comparing apples and oranges.
Well, I don't really like templates or exceptions in C++, nor
overloading (but will of course use them if I'm supposed to write C++).

So that leaves me with inheritance, which is basically just passing
somebody a function pointer (or a set of function pointers, which is the
VMT).

Also, none of the above features implies that C++ should generate more
code than equivalent C.

I'm not criticizing C++'s feature set here ;) Just saying that it
should translate down to equivalent (not too readable maybe) C.
Taking the higher abstraction C++ offers out of consideration, it is
sure that C++ will have a few overheads at places a C programmer could
easily have done better. In the past the trend was more towards
improving speed than code size.
Honestly, I don't think so. Most simple C++ features (not talking RTTI
or exceptions here) are 100% machine-translatable to equivalent C, I
would claim, with no overhead. It's just a few pointers and structs
here and there.
If you want to program against binary code you need an ABI (application
binary interface), defining what can be expected from binary code. If
some implementation detail requires two variants of a constructor to be
available, which in general are different, then both variants will be
produced so they are available at link time. Probably they will be
produced consistently for all classes, because it is an ABI.
Ok, that'd be a valid reason.
Then try the general case, find an example, where the other variant is
called. AFAIK gcc needs the second to implement inheritance, and other
C++ compilers are similar. After 20+ years there should be agreement on
the best way to implement something that basic.
But having a class BAR that inherits from class FOO is nothing different
from having a struct BAR including a struct FOO and implementing the
same functions, delegating to FOO's function as needed.

I don't need a second constructor. super() should simply call the
*usual* FOO constructor, I think.
Just in the case it helps, I think on some platforms there are
possibilities to remove unused code from the final binary at link time.

May 23 '06 #8
Me*****@gmail.com wrote:
I.e. there are two constructors, and if I use one, AFAIK only one (the
one with the '1' in the name) is used. In this case it's just a few
bytes, but I'm wondering about the general case.


just a guess.. isn't one of them copy-constructor that compiler
generates for you if you don't provide one?


That might be a real possibility. I totally forgot about copy
constructors...
May 23 '06 #9

Ulrich Hobelmann wrote:
Bernd Strieder wrote:
Try some real world sized examples. Try to support all features C++
offers, e.g. templates, exceptions, inheritance, overloading. Anything
else is comparing apples and oranges.
Well, I don't really like templates or exceptions in C++, nor
overloading (but will of course use them if I'm supposed to write C++).


"I don't like or use any of the features of this language so why is it
slower than another that doesn't have them?"

I think a better question is, why the hell did you pick it then?
I don't need a second constructor. super() should simply call the
*usual* FOO constructor, I think.


We have no way of knowing how many times you called the copy
constructor or assignment operator as you didn't post anything that
uses the class you did post. Chances are high that a *newbie* like you
might do so without knowing.

I can't tell if you are trolling or really are this dumb.

May 23 '06 #10
Ulrich Hobelmann wrote:
mlimber wrote:
Interestingly so far it seems as if I could get *more* efficient code
by writing my own C++ to C compiler (remember the very first C++
compiler?) than by using something as high-tech as GCC 4.
How do you know it generated two identical constructors? Because you
looked at the generated assembly? If it did generate a function that
you don't use (which seems more like a bug or inefficiency in your
compiler rather than a problem with the language as defined in the
C++ standard), any linker since the 1970s will strip them from the
final executable. Likewise, where did you draw your information
about the mysterious structure that the compiler generated?
They were both in the assembler output (c++ -O2 -S) and in the final
executable, as I said. The source only has one constructor (see
below), but the translation has two. I can't even *guess* how any
compiler would get the idea of doing something like this...
As already requested, please post your code for both the comparable C
program and the C++ program. That will help us get to the bottom of
this.


Sure, here goes:


[snipped incomplete code]
The output (PPC, trimmed):
__ZN3FooC2Ei:
LFB3:
stw r4,0(r3)
blr
LFE3:
.align 2
.globl __ZN3FooC1Ei
__ZN3FooC1Ei:
LFB4:
stw r4,0(r3)
blr

I.e. there are two constructors, and if I use one, AFAIK only one (the
one with the '1' in the name) is used. In this case it's just a few
bytes, but I'm wondering about the general case.


Assembly is not executable code. But if were talking assembly here's a
complete example and the complete corresponding assy from VC7.1 that shows
C++ is so efficient it doesn't generate any instructions for the class. ;-)

Without complete code one can be very mislead as to the meaning of results
taken out of context.

Jeff Flinn

foo.cpp
=======
class Foo
{
public:
Foo(int n):foo(n){}
private:
Foo();
int foo;
};
int main()
{

return 0;
}

foo.asm
=======
; Listing generated by Microsoft (R) Optimizing Compiler Version 13.10.3077

TITLE .\foo.cpp
.386P
include listing.inc
if @Version gt 510
..model FLAT
else
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS ENDS
$$SYMBOLS SEGMENT BYTE USE32 'DEBSYM'
$$SYMBOLS ENDS
$$TYPES SEGMENT BYTE USE32 'DEBTYP'
$$TYPES ENDS
_TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS ENDS
; COMDAT _main
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
sxdata SEGMENT DWORD USE32 'SXDATA'
sxdata ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
endif

INCLUDELIB LIBC

PUBLIC _main
; Function compile flags: /Ogtpy
; COMDAT _main
_TEXT SEGMENT
_main PROC NEAR ; COMDAT
; File c:\foo.cpp
; Line 15
xor eax, eax
; Line 16
ret 0
_main ENDP
_TEXT ENDS
END

May 23 '06 #11
Noah Roberts wrote:
"I don't like or use any of the features of this language so why is it
slower than another that doesn't have them?"

I think a better question is, why the hell did you pick it then?
Because, as I said, C++ is *supposed* to be pay as you go. I think even
Bjarne Stroustrup himself said that if you don't know a feature (and
supposedly MANY C++ hackers don't know all features) and don't use it,
you shouldn't have to pay for it.

We're not talking of a language with a completely revolutionary runtime
model; we're talking about C plus syntactical features.
I don't need a second constructor. super() should simply call the
*usual* FOO constructor, I think.


We have no way of knowing how many times you called the copy
constructor or assignment operator as you didn't post anything that
uses the class you did post. Chances are high that a *newbie* like you
might do so without knowing.


No, all I did was constructing an object.
I can't tell if you are trolling or really are this dumb.


Well, if this looks like a troll to you, feel free to ignore me.
May 23 '06 #12
* Ulrich Hobelmann:

take something like
class Foo
{
public:
Foo(int n);
private:
int foo;
};

Foo::Foo(int n)
{
foo = n;
}

Clearly this could be done in C by declaring Foo a struct with one
member, and by either allocating it on the stack, or by mallocing it and
calling some init-function (i.e. constructor), like void initFoo(Foo *
f, int n);.
No, it can't be done in C. You can do in both C and C++ exactly what
you describe for C: it's not limited to C. But only with C++ can you
get a construction guarantee enforced by the compiler.

That's what I'm expecting C++ to do as well, as I don't use
other features.

The output (PPC, trimmed):
__ZN3FooC2Ei:
LFB3:
stw r4,0(r3)
blr
LFE3:
.align 2
.globl __ZN3FooC1Ei
__ZN3FooC1Ei:
LFB4:
stw r4,0(r3)
blr

I.e. there are two constructors, and if I use one, AFAIK only one (the
one with the '1' in the name) is used. In this case it's just a few
bytes, but I'm wondering about the general case.


If you don't want a copy constructor, declare one and don't implement it.

Usually you do want a copy constructor.

The linker should remove any unused functions, whether the object files
are generated by a C or C++ compiler, but that's a QOI issue.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
May 23 '06 #13
Noah Roberts wrote:
I can't tell if you are trolling or really are this dumb.


Remarks like that don't help anyone in understanding the language. I
think many people wonder whether C++ has unexpected inefficiencies,
whether of necessity or because of typically poor implementations, and
the OP posted a reasonable example of a test case. Other posters have
pointed out problems with it in a courteous manner. There are enough
genuine trolls, so I suggest you hold the insults for a few minutes, as
one is sure to come along soon.

--
Ron House ho***@usq.edu.au
http://www.sci.usq.edu.au/staff/house
May 24 '06 #14
Hello,

Ulrich Hobelmann wrote:
If you want to program against binary code you need an ABI
(application binary interface), defining what can be expected from
binary code. If some implementation detail requires two variants of a
constructor to be available, which in general are different, then
both variants will be produced so they are available at link time.
Probably they will be produced consistently for all classes, because
it is an ABI.
Ok, that'd be a valid reason.


Then it is valid, because it is the reason.
Then try the general case, find an example, where the other variant
is called. AFAIK gcc needs the second to implement inheritance, and
other C++ compilers are similar. After 20+ years there should be
agreement on the best way to implement something that basic.
But having a class BAR that inherits from class FOO is nothing
different from having a struct BAR including a struct FOO and
implementing the same functions, delegating to FOO's function as
needed.


That's what you think, but an object at an address and a subobject of an
object at an address are two different things. I think, there are many
ways to get all issues done, calculating offsets, handling exceptions,
and whatever, and one way requires two variants of every constructor by
default, which might be equal, but are not in the general case. To get
a stable ABI both versions are produced by default, although it might
seem stupid to do so in the special case.

I don't need a second constructor. super() should simply call the
*usual* FOO constructor, I think.


You will have to try to solve the whole package of problems implementing
a C++ compiler to understand. Try to find a not so minimal example
spread across some translation units, where both variants of the
constructors are used, and try to understand why, or what would be more
difficult to achieve if another way had been chosen. I think the
example will have to include virtual functions to show anything
interesting, possibly even virtual inheritance. I do not know all the
details myself, but that's what I would try.

C++ has to offer quite some advantages, and it does so in a
architectured way, somehow using design patterns known before the times
of C++. If you read about design patterns, you will find the statement,
that architecture is about wasting at the right place. You are
objecting about a small wasted piece of a doghouse. The same idea
leading to a comparable piece in a skyscraper might save lots of
effort. I think you should find yourself a small house showing at least
a little bit of saving by that idea, instead of insisting on the
suboptimal doghouse. This group has seen lots of tries of proving C++
bad by doghouse examples. This is why you got so many responses you
don't like.

I think it is possible to fill several chapters introducing different
C++ implementations and comparing them. Basically this is what you are
asking for. Perhaps there is a book telling the story. (Design and
evolution of C++?). You simply cannot expect the whole deep story in a
newsgroup posting.

Bernd Strieder

May 24 '06 #15

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

22
by: Ajay | last post by:
hi! is there an authoritative source on the performance of scripting languages such as python vs. something like java, c, c++. its for a report, so it would be awesome if i could quote some...
5
by: LutherRevisited | last post by:
This may be a dumb question, but are there any practical advantages of compiling a python application to *.pyo, or *.pyc? I haven't noticed any difference in the performance of text *.py or a...
3
by: codecraig | last post by:
Hi, I have a question about Python. I know that it is an interpreted language, meaning a python program is converted to binary on the fly each time it is run, or compiled. What would be the...
26
by: billiejoex | last post by:
Hi all. I'm sorry for a noob question like this but I'll try to ask it anyway. One of the greatest problem that may discourage a new user to choose Python language is it's interpreted nature....
7
by: news.microsoft.com | last post by:
Hi, Is the compilation of XSLT, using XPathNavigator.Compile, only beneficial when the returned XPathExpression is cached? Next question, how do I cache the returned XPathExpression object? ...
4
by: Richard | last post by:
I have a service which is used to call differenct versions of an application depending on the database version that is being used. The service has been compiled in framework 1.1 and it needs to...
12
by: Wardeaux | last post by:
All, Wanting to find a way to create web pages to add to my website without having to recompile the codebehind everytime I want to add a new one... Here's the deal: I have a web app that takes...
1
by: Arpan | last post by:
I am a newbie ASP.NET programmer. While going through the MSDN ASP.NET tutorial, I came across the following sentence: All ASP.NET code is compiled rather than interpreted which allows early...
2
by: CodeMonkey775 | last post by:
I'm having problems passing a variable to a method which is executed and compiled using CodeDom. The situation is I have a List<CellData> with cells, each containing a formula (like Excel). I am...
40
by: castironpi | last post by:
I'm curious about some of the details of the internals of the Python interpreter: I understand C from a hardware perspective. x= y+ 1; Move value from place y into a register Add 1 to the...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.