Author Topic: Mixing C and C++  (Read 13551 times)

halkun

  • Global moderator
  • *
  • Posts: 2097
  • NicoNico :)
    • View Profile
    • Q-Gears Homepage
Mixing C and C++
« on: 2005-01-10 03:14:58 »
Ok, I have this sudden urge to code. For the last few days I've been pouring over Gears and looking at what I have as far as Kernel/menu and think I have enough to build a frame work of a new engine.

I have been blatently ignoreing the fieldscript opcodes.

However, my coding sucks, and I only know one API, which is Allegro. There is a GL extention(AllegroGL), which in this case, the Allegro part replaces GLUT. I find SDL way too weak for what I want. I've always found it a little too "low level" for me.

-Good Things-
AllegroGL is cross platfrom, which is great as I run linux.
I'm good with the Allegro part.

-Bad Things-
I can only code in C, and lothe OO programming execpt in some very special cases. Sadly, the orignal FF7 was done in C++ and I can't use it's code structure as a template.

I've been known to do things with pointers that's probably against the law in 37 states. What I would simply call an "Misallocated pointer" could be misconstrued as a capital offence in some countries.

I have a very weak idea of how to use filesystems in C, but we all have to learn, right?

****
I'm really attached to C, the fact that the savemap is a huge global resource make me dance with joy. I adore globals, and I know C++ hates them. However, if I was to make the Kernel in C and allow modules to be called, could a C program call a module written in C++ and  return in a sane manner?

Should I just document fieldscript?

sfx1999

  • *
  • Posts: 1142
    • View Profile
Mixing C and C++
« Reply #1 on: 2005-01-10 03:20:12 »
You would put this around your C code:

Code: [Select]
#ifdef _cplusplus extern "C" {

#endif


However, it would be inside of your inclusion guards.

Qhimm

  • Founder
  • *
  • Posts: 1996
    • View Profile
    • Qhimm.com
Re: Mixing C and C++
« Reply #2 on: 2005-01-10 05:09:47 »
Quote from: halkun
Ok, I have this sudden urge to code. For the last few days I've been pouring over Gears and looking at what I have as far as Kernel/menu and think I have enough to build a frame work of a new engine.

Speaking of legal matters, what would be the legal status of actually coding something like that? A lot of the information in Gears comes from reverse-engineering and such, and even though it enjoys legal protection in many countries, it's still a bit of a gray area, no?

Quote from: halkun
I have been blatently ignoreing the fieldscript opcodes.

Well I haven't. In the process of decoding the instructions I'm pretty much ending up writing a framework for a script enging just to "get a view of the entire puzzle". Oh yeah, that thing I promised you is still work in progress.

Quote from: halkun
However, my coding sucks, and I only know one API, which is Allegro. There is a GL extention(AllegroGL), which in this case, the Allegro part replaces GLUT. I find SDL way too weak for what I want. I've always found it a little too "low level" for me.

Me being me, I'd advise against using a premade high-level library. Better to write your own on top of OpenGL or something. Nothing is more frustrating than having things not work properly because some unknown (possibly even unaccessible) piece of code deep inside a library written by someone else isn't working like you think.

Quote from: halkun
-Good Things-
AllegroGL is cross platfrom, which is great as I run linux.
I'm good with the Allegro part.

A custom OpenGL-based library would be near cross-platform too, and things like window creation, input handling, sound etc. could and should be modularized for that very purpose. You would have to write these things to some extent anyway since no library would give you exactly what you need.

Quote from: halkun
-Bad Things-
I can only code in C, and lothe OO programming execpt in some very special cases. Sadly, the orignal FF7 was done in C++ and I can't use it's code structure as a template.

Heh, I don't loathe OO programming itself, though I dislike how things like virtual functions (what the wonderkids call "the point" of OO) create hidden bottlenecks you can't affect. Personally I see OO as a way to create nice code, and thanks to C++'s C inheritance I can more often than not write code that is as efficient as pure C but incredibly more easy to read and debug. C is great for low-level, and in combination with inline assembler it gives you perfect control, but it is sorely lacking in structure; or rather, you can certainly create well-structured programs but mostly at the expense of code readability.

I'd strongly recommend having a look at some of the more basic C++ concepts. If only for the increased code structure, which helps immensely in larger-scale projects. And let's not forget my favorite, operator overloading. The perfect union of highly custom data types and sensible code. Stuff away the nasty bits of code in a secure place and never risk fucking up the implementation part from your actual program code. But enough C++ advertising.

Quote from: halkun
I've been known to do things with pointers that's probably against the law in 37 states. What I would simply call an "Misallocated pointer" could be misconstrued as a capital offence in some countries.

I'd love to hear your stories. ;) What, by the way, is a "misallocated pointer"?

Quote from: halkun
I have a very weak idea of how to use filesystems in C, but we all have to learn, right?

Well since all the library calls get translated into the appropriate system calls, I guess it doesn't matter which library you use. For the FF7 engine I guess you'd rarely need more than simple fopen calls, but file structures are really ideally handled by some simple classes. One for normal files, built-in compression handlers, one for LGP encapsulation... well, learning is of course essential in any case. I'm just mumbling incoherently now, it seems.

Quote from: halkun
I'm really attached to C, the fact that the savemap is a huge global resource make me dance with joy. I adore globals, and I know C++ hates them. However, if I was to make the Kernel in C and allow modules to be called, could a C program call a module written in C++ and  return in a sane manner?

Well a global is really just a weak implementation of the singleton pattern. Only problem with globals (in any case) is the nasty amount of attention you have to spend to specify where they're allocated. But wrap it up in a simple class with static members and suddenly the C++ guys think it looks better too... Anyways, C++ and C are mostly compatible with a few exceptions; calling conventions (works OK by default), name mangling (hence the need for extern "C" for inter-module calls) and exception handling (which can of course be done using more platform-specific methods, but for portability's sake should be kept to standard forms or not at all. It is quite useful though, especially for writing kernel-like applications). So you have to mind a few things when mixing the two, but generally it's no problem. Without exception handling you really only need the extern "C" to be sure, everything else should work fine.

Quote from: halkun
Should I just document fieldscript?

I could easily start putting together a "real" field script engine, but without a game around it it would merely be a hypothetical machine with very limited use (just a way to test if I got the semantics if certain op-codes right by executing a field script where they occur). I know enough of the FF7 interpreter to implement the basics. The FF7 interpreter is, by the way, flawed in many respects and relies heavily on the discipline of the script writer/compiler to prevent things like control flow jumps and request from being simply lost, resulting in lock-ups. I already have a half-working alpha version of a FF7 script compiler, though I obviously had to invent much of the "uncompiled" language myself.

halkun

  • Global moderator
  • *
  • Posts: 2097
  • NicoNico :)
    • View Profile
    • Q-Gears Homepage
Re: Mixing C and C++
« Reply #3 on: 2005-01-10 05:33:50 »
Quote from: Qhimm

I'd love to hear your stories. ;) What, by the way, is a "misallocated pointer"?


A "misallocated pointer" is a pointer I "lost" either becuase it was in the source code and I had no idea what it did, or I simply lost it in the source itself. When I would call upon the beast, it usally belched out garbage at me.  

I like to call this "Programming on accident"

My worst crime was I used a pointer to point at frame buffer bitmaps so I could swap pages on vsync. However I was allocating space for a new buffer every frame and could not track down where in my code the allocation was taking place. I was, however, able to destroy the bitmaps using an allegro command and free up the memory I was eating up. I coudn't destroy the bitmap in the framebufffer loop because that erased the backbuffer I was drawing on.

My solution?

I gave my game a "Timer"  based on how much RAM you had. It just happened that when the time ran out, you were also almost out of memory. One quick destroy_bitmap(*bitmap) cleard the whole thing I could make a new surface with a "Game over" Logo.

Needless to say, I never released it ^_^;

Qhimm

  • Founder
  • *
  • Posts: 1996
    • View Profile
    • Qhimm.com
Mixing C and C++
« Reply #4 on: 2005-01-10 06:31:47 »
LOL you certainly managed to top even my wildest expectations then!

mirex

  • *
  • Posts: 1645
    • View Profile
    • http://mirex.mypage.sk
Mixing C and C++
« Reply #5 on: 2005-01-10 11:15:59 »
LOL @ Halkun's last post. You can call that wild programming ! :-D

To the topic:
Quote from: Qhimm
A custom OpenGL-based library would be near cross-platform too, and things like window creation, input handling, sound etc. could and should be modularized for that very purpose. You would have to write these things to some extent anyway since no library would give you exactly what you need.

Yea but its very time-consuming. I've just started working with SDL, and it looks good for keyboard & mouse handling (they say it can handle joysticks and such in a good way too); fmod library looks good for handling sound & music; hmm and for creation of windows ... maybe WxWidgets could be used. All of these libraries are cross-platform. Though so far i use only SDL (i use it for 2d graphics and imput handling).

about C++:
I'd recommend everyone who knows C to learn C++. Its not so hard. And code gets more tidy and packed into separate sections, which cannot affect any other section if you dont want them to.

Simply said C++ just adds class stuff. Thats the most important thing imo.
I would recommend to look at these classes, and their private and public properties. Inheritance of classes can be little confusing, so dont look at it untill you feel comfortable with classes. Just try to mess around with classes. Classes are same as structures (they store data) and they also store functions that can work with that data.
Halkun If you want i can tell you how everything works, we could meet on Icq or Irc ...

Alhexx

  • *
  • Posts: 1894
    • View Profile
    • http://www.alhexx.com
Mixing C and C++
« Reply #6 on: 2005-01-10 14:22:35 »
I think that writing a cross-platform OpenGL system *shouldn't* be that hard after all. There's a public open-source 3d engine called Irrlicht which is doing that.
We just need to make all basic functions (window creation, OS communication, File system) cross-platform... or am I wrong?

halkun:
Just a question: Does this mean that you think about writing a new FF(7) engine?

 - Alhexx

 - edit -
Well, what do you mean by cross-platform anyway? Windows/Linux ?
PC/Console?

sfx1999

  • *
  • Posts: 1142
    • View Profile
Mixing C and C++
« Reply #7 on: 2005-01-10 19:54:50 »
I love objects! I like virtual classes, too. I mean, I can do this:

Code: [Select]
class shape
{
  public:
    virtual void draw(void);
};

class triangle:public shape
{
  public:
    void draw(void) { thedrawingcode; }

    point p1, p2, p3;
};

class rectangle:public shape
{
  public:
    void draw(void) { thedrawingcode; }

    point p1, p2, p3, p4;
};

shape thearray[16];

int i;
for (i=0, i<16, i++)
{
  if (i<8)
    thearray[i] = new triangle;
  else
    thearray[i] = new rectangle;
}

for (i=0, i<16, i++)
{
  thearray[i]->draw();
}


I also hate SDL. It is a nightmare. It replaces your main function and causes all of these linker errors, and forces lines to print to files.

halkun

  • Global moderator
  • *
  • Posts: 2097
  • NicoNico :)
    • View Profile
    • Q-Gears Homepage
Mixing C and C++
« Reply #8 on: 2005-01-11 00:41:12 »
Quote from: Alhexx

halkun:
Just a question: Does this mean that you think about writing a new FF(7) engine?

 - Alhexx

 - edit -
Well, what do you mean by cross-platform anyway? Windows/Linux ?
PC/Console?



Well, There have been lotsa engines that have been rebuilt and updated for newer computers.

xu4 for Ultima 4, Exult for Ultima 7, Sarian for Sierra AGI games, FreeSCI for Sierra SCI games, ScummVM for Lucasarts games.

I really don't see any reason why a new FF7 engine can't be written. Of course, you would have to start small. I mean, loading and parseing "STARTMAP" can be a start. It's not like it's expected to play the movies and do video overlays right out of the gammit.

I mean, we can load the little SD entities, and animate them. We can load the backgrounds, we can sort of load the walkmesh and sort of set the camera angle. Qhimm's workingon the field script, I'll plug along at the rounding out the data. It's really trvial to alter FF7 in a PSX emulator once you know where the data is.

Here's another kicker.

Once upon a time I was granted a power to see two "remake" forums, which have fallen into disuse. Most of the "secret" stuff was moved into the open. To me, making FF7-2 is a silly endevour now as Square seems to be making a much better job of it than we can ala "Advent Children"

Why not learn a little and create this. Heck, I'll even learn C++ (grumble) if you need someone to make a first step. I have a 8 year old C++ book that has never been touched.

WOW, going though the "remake forum", I've found some really old and funny things. How's this cira 2002.

Quote
Posted: 2002-03-09 09:36

I'm going to post this is in main forum too, but I'd decided to start here.

I wish tto collect all of what we learned about Final Fantasy and put them all in one place. I know that there are some out there who haved already amassed documents, but I wish to have one, comprehensive overview of the FF7 engine. Kind of like my PSX documentation project I did way back when. I was wondering if you all could point me to notes whatever working notes you have so I can put them togeather into some kind of order. This way we can start looking at the blanks of what's left over so we can start to fill in the gaps. (I know, there a alot of gaps) You guys can email me at [email protected] with a link or any docs you have. I think it will benifit all.
-halkun


WOW, it took me almost *THREE YEARS* to get around to writing Gears ^_^. That email is desfunct BTW, as is the ISP, which was also my old job.

By ross platfrom, I'm thinking not only Linux, Mac, and PC, but also has the ability to accept differnt media too. (Both PC and PSX)  Sadly, most Linux computers can't mount Mode 2 disks with CD-Rs (PSX format) correctly and that might be a problem...

Qhimm

  • Founder
  • *
  • Posts: 1996
    • View Profile
    • Qhimm.com
Mixing C and C++
« Reply #9 on: 2005-01-11 11:25:11 »
Aaaand... of course sfx1999 manages to bring out my least favorite feature of OOP as an example :P

Seriously though, I wholly think the best path into C++ (specifically performance C++) from C is through the mindset that classes are just intelligent structs. Writing a binary stream handler in C would typically involve some kind of struct containing current stream data, and passing a pointer to that struct as a parameter to a set of functions dealing with the stream. All in one namespace of course, giving you code like:
Code: [Select]
binary_stream_t* stream = binary_stream_create(data, length);
binary_stream_read(number_of_bits, &data_var, stream);
binary_stream_close(stream);

Clearly a nasty and rather cluttered case. C++ classes are ideal in these cases, since member functions implement exactly the same pattern: passing a pointer to the data struct as a required (hidden) parameter. Rewritten as C++, you'd get:
Code: [Select]
binary_stream stream(data, length);
stream.read(number_of_bits, &data_var);
stream.close();

Easier to code, easier to read, exactly the same program. The C++ might actually be more efficient since many compilers optimize the passing of the 'this' pointer (pointer to object/struct data) in a CPU register.

This is probably the primary advantage of C++ on an early stage of learning, and especially for this application (low-level coding of the FF7 engine, which already relies heavily on structs). As long as you stay out of the more advanced areas of OOP such as sfx1999's example, C++ usually behaves just like C code, but with more options for structuring your code more intuitively.

Now if you *really* want to get into the interesting bits, look into templates and metaprogramming. These are my personal favorite aspects of the C++ language, since I feel it to be an extremely good example of combining very high-level constructs with very low-level control and performance. Some people are even implementing new languages in C++, such as the boost spirit library, which allows you to process BNF grammars in C++ by entering the grammar itself (very slightly modified) into your code. Unfortunately most of today's explorers of these areas are constantly running into the limitations of C++. I feel there's a need for a new language or an upgrade to C++ to allow it to expand further upwards without sacrificing its low-level attention to detail. As it is, there's just no other language out there even close to being able to replace C++'s role as a performance *and* structured programming language.

</rant>

Alhexx

  • *
  • Posts: 1894
    • View Profile
    • http://www.alhexx.com
Mixing C and C++
« Reply #10 on: 2005-01-11 21:38:25 »
halkun: Hey, yeah!

If we are really going to start this - then I can offer my programming "skills", too...
I surely cannot program as good as your or Qhimm (and of course some others), but I think I can give you a hand at some points.

So you've got me on your side when this is going to happen!
:D

 - Alhexx

 - edit -
erm - one more question:
Are you aiming at an "engine-rewriting" project only or at a complete remake (as ficedula started it) ??

halkun

  • Global moderator
  • *
  • Posts: 2097
  • NicoNico :)
    • View Profile
    • Q-Gears Homepage
Mixing C and C++
« Reply #11 on: 2005-01-11 22:58:24 »
No, a new engine. Think of it like the Linux kernel without any helping programs. The system would need kernel.bin, window.bin, and the many many lzs files for example..

Kind of like a PSX emulator withut any games or a BIOS. I mean, it can still execute, but without any data, it doesn't to very much. I'm not saying write an emulator though, but a new engine that can take the data.

Here's a challange. I'm going to see if I can write a program that can open kernel.bin, uncompress it, allocate the save map, and copy section three (The savemap initilazation data) into it, and start the gameclock.

I mean, that's nothing, but it's a core thing the game goes.

After that I'm sure I can allocate structs and load in the item/object data from kernel.bin. Still no game, but now I have more "stuff" in memory, and then start the game clock.

You see where I'm going with this?

Alhexx

  • *
  • Posts: 1894
    • View Profile
    • http://www.alhexx.com
Mixing C and C++
« Reply #12 on: 2005-01-11 23:07:19 »
I see...

 - Alhexx

 - edit -
But this, however, seems to be a good preparation for re-starting the FF7 Remake project...

sfx1999

  • *
  • Posts: 1142
    • View Profile
Mixing C and C++
« Reply #13 on: 2005-01-12 01:59:21 »
I still haven't found a need for templates, but what exactly is metaprogramming?

Also, STL is cool. I was looking into some of the classes (std::vector, std::string, std::list, and std::deque), but I don't need them yet.

Qhimm

  • Founder
  • *
  • Posts: 1996
    • View Profile
    • Qhimm.com
Mixing C and C++
« Reply #14 on: 2005-01-12 04:12:41 »
In short, metaprograms are programs that produce code (that in turn produce the actual program). A very simple example are preprocessor macros, and one use for those is shown in Microsoft's message maps (MFC, WTL). When you use preprocessor macros in your code, these eventually expand into the actual code, which is then compiled.

You can do the same thing (but more) using templates, thanks to the fact that templates are evaluated at compile-time (metaprogramming is sometimes referred to as compile-time programming). You can write a recursive template to calculate the n'th prime number, for example, then accessible as a constant in your program with "prime_number<4>::result" (or similar), which would yield the number 7 (or 11, depending on whether you think zero-based). The point is that all work is done at compile-time, and the only thing that ends up in your actual program is a constant.

Metaprogramming can also be used to simplify your code, for example by recursively defining common iterative tasks (again, the end result in your program is simple code -- only the source code itself is defined iteratively, not the program function).

The advantage? High-level metacode --> lower-level source code --> efficient compiled code. Because it's high-level, the code is easier to maintain (although it might not always look like C++ any more...). Because the actual source code being compiled is low-level, the compiler can better generate efficient code. Without metaprogramming, you usually have to make runtime accomodations in order to write high-level code, which is a performance hit.

Basically metaprogramming helps bring the code you actually write closer to your ideas, while keeping the actual program close to the CPU. It's abstraction like many high-level languages provide for you, but you wrote that abstraction. You know exactly what it does, and can replace any part of it. Imagine creating your own high-level language which compiles into C++ code, so that not only does it generate C++ code, it actually compiles using the C++ compiler! The C++ compiler expands and evaluates your source code over and over again until only pure, compileable C++ code is left, which then becomes your actual executable.

</passionate>

mirex

  • *
  • Posts: 1645
    • View Profile
    • http://mirex.mypage.sk
Mixing C and C++
« Reply #15 on: 2005-01-12 06:34:54 »
I don't know if i get it, so shortly said metaprogramming means using macros ?

Well templates look nice, but hmm .. I somehow don't like them :). I like only one example of templates which is CArray (from MFC library) its an array class which can be used with any type ( int, long, or even with your own new types, structures, classes or anything), because its defined something like this:

Code: [Select]
template CArray< type, type*> {
  type  *data_array;

  int AddMemberToTheArray( type a );
  int RemoveMember( type a );
  type GetAt( int position );
}


so if you want to use it for your structure
Code: [Select]
struct s_person {
  long age;
  long height;
  long weight;
  char name[ 128 ];
} ;

you can. Like this.
Code: [Select]
// define array like this
CArray< s_person, s_person > ArrayOfPersons;

s_person new_guy;

// and you can use it with defined type
ArrayOfPersons.Add( new_guy );

// and you can use it on different types too.
CArray< int, int > IntArray;
CArray< unsigned short, unsigned short > USArray;
CArray< void*, void* > VpArray;


But i dont see any other use than that. :(

Qhimm

  • Founder
  • *
  • Posts: 1996
    • View Profile
    • Qhimm.com
Mixing C and C++
« Reply #16 on: 2005-01-12 06:58:36 »
Well suffice to say metaprogramming is much more than simple macros, but since macros is a form of metaprogramming I guess the comparison holds. :)

Okay, quick example of other use of templates, then. What about this?
Code: [Select]
template< class TYPE >
class SomeSpecificClass : public TYPE {
    // ...
};

As a way to modify SomeSpecificClass' precontitions without having to touch the source file? Or:
Code: [Select]
template< typename FNCT >
void doSomethingWithCallback(int arg1, int arg2, FNCT callback) {
    // ...
    callback(some_parameters);
}

With the sometimes handy quality that it callback can be *any* object that accepts operator() calls with a parameter set which can accept some_parameters, be it regular function pointers or functor objects. Or a more calculative form of templates:
Code: [Select]
template< int nBits >
class BitSizeType {
    // Define the following with the help of specializations:
    typedef type_that_can_contain_at_least_nBits_bits type;
};
template< int nChars, int nBitsPerChar >
class SimpleCharBuffer {
    BitSizeType<nBitsPerChar>::type m_charArray[nChars];
};

Templates can help you abstract away many kinds of code into generic counterparts (like your CArray example), eliminating the need to be overly (and repetitively) specific.

mirex

  • *
  • Posts: 1645
    • View Profile
    • http://mirex.mypage.sk
Mixing C and C++
« Reply #17 on: 2005-01-12 08:29:42 »
Well but usually you know EXACTLY what you want to do so they are excessive. Like you usually know what you want to return in callback.

Qhimm

  • Founder
  • *
  • Posts: 1996
    • View Profile
    • Qhimm.com
Mixing C and C++
« Reply #18 on: 2005-01-12 08:39:18 »
Usually you do, within your own code. For writing a library, that kind of thinking results in very limited usability. I guess reusability and building libraries is really one of the widest applications of templates today. Almost all large C++ libraries (general-purpose libraries, that is) depend in some way on templates.

Cyberman

  • *
  • Posts: 1572
    • View Profile
Mixing C and C++
« Reply #19 on: 2005-01-12 16:39:29 »
Templates make things simpler with complex object and libraries.  For example creating arrays of new object types is a simple example of the use of templates.  Think of a template as a stencil that allows you to paint your own objects at compile time.  That's as simple as it is.  Template uses include set types lists arrays sparse matricies.

I've only used them on ocassion, namely in sets that are enumerated. For example you are creating an object with a property that has a set of information reguarding it's style. Example a form you can add frm_Maximize frm_Minimize frm_Close frm_System.  These all add buttons to the forms toolbar at run time.  You can create these much more easily using a template than having an unsigned long that contains bits that need to be set.  When these are accesss code can be used to translate this information to a windows API command.   It makes your program appear relatively simple inspite the fact a lot of things are happening in the background.  Borlands VCL uses this extensively.


As for an FF7 engine.. hmmm might be fun to work on.   I've been monkeying with the data formats and wanting to get a script interpretor running myself.  The key to such an engine is to be able to work with the existing data without translation or manipulation.   Of course with the PSX version things might suck big time if you want to play a movie (LOL) nothing like read 2352 bytes of data and inspecting it carefully to be sure it's the right kind of data (rolls eyes).  (Wait is this interleaved audio or is it video or is it raw data?)

Cyb - At this point I'm almost ready to restart working on FF7 data. Woo?

ficedula

  • *
  • Posts: 2178
    • View Profile
    • http://www.ficedula.co.uk
Mixing C and C++
« Reply #20 on: 2005-01-12 17:45:27 »
Borland's VCL doesn't really use templates, because it's written in Delphi, which doesn't have templates. However, I could well believe the C++ interfaces to it needed to use templates in order to support sets - something Object Pascal has in the language.

While not templates, C# is at least getting generics in 2.0 ... which means Delphi will be getting it too, thank goodness ;)  In fact, it's possible D2005 has it already.

sfx1999

  • *
  • Posts: 1142
    • View Profile
Mixing C and C++
« Reply #21 on: 2005-01-12 21:14:22 »
I have to say, there isn't much use for macros in C++. I mean, you can just use inline functions and templates, and they are type safe, not to mention they can be debugged easier.

Qhimm

  • Founder
  • *
  • Posts: 1996
    • View Profile
    • Qhimm.com
Mixing C and C++
« Reply #22 on: 2005-01-13 02:44:57 »
Quote from: sfx1999
I have to say, there isn't much use for macros in C++. I mean, you can just use inline functions and templates, and they are type safe, not to mention they can be debugged easier.

There is a definite use for macros in C++, even though the "pure" scholars try to deny it. For example, you might have a very common kind of loop with the same instructions done at the start and end every time. Would you rather write:
Code: [Select]
// ...
for ( ... ; ... ; ... ) {
   // ...
   actual_code_unique_to_this_particular_loop;
   // ...
}
// ...

Or, with the use of macros, you could:
Code: [Select]
#define BEGIN_LOOP(args) ...; for ( ... ; ... ; ...) {
#define END_LOOP(args) ...; } ...;

BEGIN_LOOP(args)
    actual_code_unique_to_this_particular_loop;
END_LOOP(args)


Macros are low-level and have some severe limitations, but since they're purely text-based and work entirely outside of C++, you can do some very useful things that would simply not be possible in C++. How would you declare a new scope and fill it with user-supplied code (see example above) in C++?

The whole reason people use them these days is for reducing code redundancy and improving code readability and maintainability. Personally, while making a program relying heavily on arrays and maps and being able to traverse the elements of these, I felt the need for a foreach statement in C++. Of course there isn't one, and there's no way to implement one inside of C++ (that looks pretty, anyway). But with macros, you can usually hide away all the nitty-gritty details inside a simple for statement, giving:
Code: [Select]
#define foreach(type, item, container)   for ( ... ; ... ; ... )

foreach( int, value, some_array ) {
    printf("%d\n", value);
}

Not perfect, and the foreach macro wouldn't behave exactly like C++ (no space allowed between foreach and the opening parenthesis, for example), but you have to admit that's pretty damn more handy to code than manually messing with iterators or Microsoft's POSITION values every time you just want to simply step through all items in a container. This simple solution would not be possible without preprocessor macros.

That having been said, there are plenty of ways to use macros badly. But I usually say that as long as each macro keeps a clear semantic meaning, they do not obstruct debugging (unlike macros that have you wondering "what the hell does this do?"). Special care must of course be taken too, so you don't clutter up the variable name space with "hidden" variables declared from inside macros; these are much harder to debug, of course. An ideal macro does what it appears to do, and nothing else.

As for type safety, well, I usually say that macros should never be used in situations complex enough for type safety to become an issue. That having been said, ironically templates are often used to get around type restrictions, i.e. have them act more like macros which accept anything, and let the compiler gawk if it doesn't work with the underlying code.

sfx1999

  • *
  • Posts: 1142
    • View Profile
Mixing C and C++
« Reply #23 on: 2005-01-13 03:53:59 »
I didn't say they useless, now. You can use them for inclusion guards. :D

mirex

  • *
  • Posts: 1645
    • View Profile
    • http://mirex.mypage.sk
Mixing C and C++
« Reply #24 on: 2005-01-13 06:33:21 »
Qhimm: i think that too complex macros are hard-to-read, because it takes some time to figure out what are they doing. I would use inline functions instead, because they do similair thing as macros (replace their referece with code) and are easy to read and debug.

Well and guys lets keep it simple here, or Halkun will get scared of C++ :)