Solved

Porting C to C++

Posted on 2001-08-11
7
259 Views
Last Modified: 2010-04-02
Hi.

I am in the process of moving a project from C to C++. We are talking about a project comprised of 10 C modules where only the main() function is in a C++ module.
This is a widely distrubted software running on many remote machines at nearly real-time environemt and performing very-high-priority tasks, thus I cannot make mistakes...
As the first step I renamed all the C modules to CPP and removed all the extern "C" from the code. The first thing that comes up is type-casting errors where C++ is more restrictive. Should I use the dynamic_cast and reinterpret_cast or rather the usual (type) cast?
Also any more vital advises you've got? (especially regarding how to prevent even the slightest decent in performance and stability)

Please respond ONLY if you had true experience with such an issue.

More info:
The reason I move from C to C++ is the compulsory need to use a C++ third-party code. I am not planning on changing the structure of my existing code.
The application relies stongly and deeply on alignment of the data structure. Should I be worried of alignment that is going to change in my sturcts?

Thanks.
0
Comment
Question by:mathought
  • 2
  • 2
  • 2
  • +1
7 Comments
 
LVL 32

Expert Comment

by:jhance
ID: 6376159
>>The application relies stongly and deeply on alignment of the data structure. Should I be worried of
alignment that is going to change in my sturcts?

My biggest concern here would NOT be from C -> C++ but rather from one vendor's compiler to another's.  (As least I think that's what you are saying.)
0
 
LVL 6

Expert Comment

by:Triskelion
ID: 6376192
The alignment issue can be solved with a compiler option
 (like /Zp1 in MS compilers).

I once had the task of converting legacy C code (I inherited (pun intended)) to be included with new C++ code.
OS=MSDOS

The best advice I have is to only modify what's necessary.
I used the old-style casts where necessary.  There were not many.  I also re-evaluated the use of certain data types that required me to cast.  In the process, I cleared up some potential bugs.

Then I got curious and started wrappering the old functions into classes.  I learned a lot about the original design, but rewrote at least 25% of the code.

Later, that code had to be re-compiled for WinNT.  Luckily, I had made classes out of the old code.  It made the conversion (practically a rewrite) easier.  The conversion was pretty much a determination of what I could actually use.  Having 'like' grouped functionality in classes was a tremendous help.

Part of your decision has to do with your timeline, your familiarity with the original design and any future application for the code (or entire program).

If you're a true geek, you can compile and run the minimally changed code at work and do heavy experimentation at home.  Nothing to lose but time.
0
 
LVL 7

Accepted Solution

by:
peterchen092700 earned 100 total points
ID: 6376379
a) do you need to call the C++ code from inside the C code?if not, you can wrap everything that "remains C" in
extern "C" { /* C code here */ }

* Alignment: /Zp1 (align by one byte) can be a bad idea if the original compile used word or DWORD alignment *and* the code relies on this. I would run the "old C" code and trace the structure sizes. then place asserts in you cpp code like 'assert(sizeof("NastyStruct") == 47)'. oh, and make sure that the byte size of char is the same on both compilers.

* Bit packed structures: Bits can be your downfall. if the code uses sth like
struct Bitpacked {  
  int x : 4;
  int y : 3;
};

there are several issues: a) the size of the entire thingie (esp. when size is less than sizeof(int)), and b) the location of the individual bits. You typically can control a) by a compiler option, but with b) you can't do much except rewriting your code. Most compilers do pack such structures tight, but they are allowed to add pd bits - e.g. to move y to the beginning of the next full byte)

* Warning Level:
A good idea is to the maximum warning level (typically 4), and examine all warnings seriously. This may be tons if you come rom C, so just clean up all warnings at Level 3.

* ANSI compatibility
If the original code is ANSI compatible, check the cpp compiler for an option like "ANSI compatibility mode", or "disable Non-standard extensions".

* Type casts: you should get along with static_cast, and reinterpret_cast where necessary. dynamic_cast is a C++ class specific cast. However, you should understand all casts and the difference beetween them. In short:

static_cast : implicit casts that sometimes come with a warning (like loosing precision):

int i;
char c = (char) i;
char c = static_cast<char>(i);

reinterpret_cast: "hard" cast - "interpret these bits as if they were of type <foo>"

void * p;
long l = *(l *)p
long l = *(reinterpret_cast<long *>(p))

(BTW, I have the habit to use C-style casts throughout my c++ projects, but it' a good idea to check each cast when coming from C, since existing C code tends to rely on compiler  & platform dependent facts)

It's been a long time since I did C --> C++, but I'm looking forward to ASM ==> C++ next year ;)

Good luck, and happy testing
Peter
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 6

Expert Comment

by:Triskelion
ID: 6376391
I agree with peterchen's assessment on the /Zp1 thing.
It sounded as if I was suggesting to 1-byte align the code, but I should have said to match the byte alignment with the /Zp(n) option (if you use a compatible compiler).
0
 

Author Comment

by:mathought
ID: 6376901
I appreciate the advices, there is also one more issue. is it safe to replace all malloc() to new? Should I expect different behaviour once I move to new instead of malloc?
0
 
LVL 7

Expert Comment

by:peterchen092700
ID: 6376955
depends on what you call (or rather: your existing source) "different".

Practically, I would make this decision dependent on how much you expect the project to change *after* being revamped to C++. If you don't expect the project to grow very much, I'd strongly suggest stay with malloc/free, as the change is error prone and the only benefit you don't have the hassle of mixing delete and free later.

Technicaly, the following differences exist or can exist:

new/delete calls constructors & destructors on it's elements. Since they are most likely intrinsic vars structs that don't have such, there sould be no *real* difference

new is "type-aware". Although it's common to replace malloc(n) with ((void *)(new char[n]), and free(p) with delete ((char*)p), this has no "positive side effect" and it might be dead wrong on some compilers and platforms, for memory alignment and byte size of "char". It works on an x86 platform, though.

the actual memory allocated by new may differ (storing array lenght, using different allocation scheme,...) VC++' new calls malloc internally.

most compilers offer a non-standard "get allocation size" function for malloc, but not for new.

All these differences are negligible if the C code is well written - but the C I encountered (or wrote) often tends to rely on implementation specifics, so your milage may vary. Anyway, if your code ist that crude, it might not even survive the new compiler.

Peter
0
 

Author Comment

by:mathought
ID: 6381112
Thanks for the descriptive commnts, everyone.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

948 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now