Solved

Porting C to C++

Posted on 2001-08-11
7
249 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
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
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

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

744 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

11 Experts available now in Live!

Get 1:1 Help Now