Having C code looking like C++ code

Discussion in 'C Programming' started by Fronsac, Oct 12, 2003.

  1. Fronsac

    Fronsac Guest

    Hi,
    I've been asked in a job interview how to make C code look like C++
    code, and honestly I didn't know what to answer because I have never really
    done a lot of C. Now, I've been searching around the web about web sites
    that talk about this subject, but I've had no luck. Can anyone point me to
    some web site about this subject? Thanks a lot!
     
    Fronsac, Oct 12, 2003
    #1
    1. Advertising

  2. Fronsac

    bd Guest

    Fronsac wrote:

    > Hi,
    > I've been asked in a job interview how to make C code look like C++
    > code, and honestly I didn't know what to answer because I have never
    > really done a lot of C. Now, I've been searching around the web about web
    > sites that talk about this subject, but I've had no luck. Can anyone point
    > me to some web site about this subject? Thanks a lot!


    Making C code look like C++ generally requires making it actually be C++.
    Why would you try to make one language only look like another? There's no
    advantage, unless you're trying for the IOCCC.
     
    bd, Oct 12, 2003
    #2
    1. Advertising

  3. In article <AL1ib.48789$>,
    Fronsac <> wrote:
    >Hi,
    > I've been asked in a job interview how to make C code look like C++
    >code, and honestly I didn't know what to answer because I have never really
    >done a lot of C. Now, I've been searching around the web about web sites
    >that talk about this subject, but I've had no luck. Can anyone point me to
    >some web site about this subject? Thanks a lot!


    Answer #1: Why would you want to?
    Answer #2: By writing bad C code
    Answer #2b: By writing C code that looks like bad C++ code
    Answer #3: By writing in the common subset of C and C++ (but see #1 and #2)
    Answer #4: What are you really trying to find out?

    One possibility is that they want C++-clean C code for a possible upgrade
    path to C++. The correct solution to this is to use C++'s `extern "C"'
    to allow C and C++ code to be linked together, and have C (compiled as
    C) and C++ (compiled as C++) linked together when they want old (C)
    code and new (C++) code in the same program. All that this requires
    is that the header files used be both C-clean and C++-clean, which is
    rather easier than the general case of all code.


    Unless they're talking about all the angle brackets that C++ uses.
    You might be able to get away with using the <: and :> digraphs for that.


    dave

    --
    Dave Vandervies
    >till not good enough for Richard Heathfield, but what can you do, really?

    You could always write "only for clever people" on the cover.
    --Ben Pfaff and Richard Heathfield in comp.lang.c
     
    Dave Vandervies, Oct 12, 2003
    #3
  4. Fronsac

    Fronsac Guest

    > Making C code look like C++ generally requires making it actually be C++.
    > Why would you try to make one language only look like another? There's no
    > advantage, unless you're trying for the IOCCC.


    C++ is not always accessible on some platforms (think game consoles like the
    old game boy might not have access to a C++ compiler), so you'll have to use
    C and some tricks to have it behave like C++. From what I've gathered so
    far, it's impossible with C syntax to achieve inheritence, though you can
    fake it. For example :

    struct Foo {
    int var1;
    }

    struct Bar {
    struct Foo base;
    int var2;
    }

    Bar* createBar() {
    return malloc( sizeof(Bar) );
    }

    void foo_incVar1( Foo* foo ) {
    foo->var1++;
    }

    void bar_incVar2( Bar* bar ) {
    bar->var2++;
    /* though, you realize that if I want to access var1, I have to do
    bar->base.var1, or ((Foo*)bar)->var1).
    The thing that bugs me most though is that you can encapsulate your
    data. */
    }

    void main() {
    Foo* foo = (Foo*) createBar();
    foo_incVar1( foo ); /* increments var1 */
    bar_incVar2( (Bar*) foo ); /* increments var2 */
    }

    And you can use function pointers to simulate virtual methods for your
    "objects".
     
    Fronsac, Oct 12, 2003
    #4
  5. "Fronsac" <> wrote:

    >Hi,
    > I've been asked in a job interview how to make C code look like C++
    >code, and honestly I didn't know what to answer because I have never really
    >done a lot of C. Now, I've been searching around the web about web sites
    >that talk about this subject, but I've had no luck. Can anyone point me to
    >some web site about this subject? Thanks a lot!


    You posted the same question with slightly different subject lines
    to (at least) a.c.l.l.c-c++ and c.l.c.

    If you feel the need to post to more than one news-group, please
    cross-post rather than multi-post. Thank you.

    BTW: C++ is off-topic in c.l.c.

    Irrwahn,
    change codepage to make english text look like chinese text.
    --
    Three is no spimle sbtsuuttie for cearful, cercrot,
    wtlirtew-len Esglinh. Tehre is no slveir beullt.

    (Rhacrid Hfiaehlted in c.p, 2003-09-25)
     
    Irrwahn Grausewitz, Oct 12, 2003
    #5
  6. Fronsac

    Nathan Guest

    > Hi,
    > I've been asked in a job interview how to make C code look like C++
    > code, and honestly I didn't know what to answer because I have never

    really
    > done a lot of C. Now, I've been searching around the web about web sites
    > that talk about this subject, but I've had no luck. Can anyone point me to
    > some web site about this subject? Thanks a lot!


    Hi,

    Do you mean you want to do object oriented programming in C? In that case,
    there are many ways of doing this. The following article describes one way:
    http://www.accu.org/acornsig/public/articles/oop_c.html

    Regards,
    Nathan
     
    Nathan, Oct 12, 2003
    #6
  7. Fronsac

    Fronsac Guest

    > You posted the same question with slightly different subject lines
    > to (at least) a.c.l.l.c-c++ and c.l.c.


    Yeah, I was too lazy to copy-paste the subject line from the other post. I
    posted in two forums just to be sure at least one person answered me. :)

    > If you feel the need to post to more than one news-group, please
    > cross-post rather than multi-post. Thank you.


    What is cross-post? Could you explain me what it is and how to do it? Thanks
    a lot.

    > BTW: C++ is off-topic in c.l.c.


    That's fine. I only asked here because I wanted to know more about a certain
    way to code in C, and I thought here would be a great place to start.
     
    Fronsac, Oct 12, 2003
    #7
  8. Fronsac <> scribbled the following:
    >> If you feel the need to post to more than one news-group, please
    >> cross-post rather than multi-post. Thank you.


    > What is cross-post? Could you explain me what it is and how to do it? Thanks
    > a lot.


    Cross-posting is posting the same article to multiple newsgroups
    simulatenously. Not identical copies of the article - the SAME article.
    How to actually do this depends on your newsreader. All that is NEEDED
    is that the NNTP headers have a "Newsgroups:" line consisting of
    multiple newsgroup names (separated with commas), but not all
    newsreaders allow you to edit NNTP headers directly. (tin, which I use
    myself, does.)
    Another way, and one recommended for Usenet beginners who don't yet
    know how NNTP works, is to look around the "compose message" (or
    similar) window and search for a text box labelled "Newsgroup" or
    something. Then just type multiple group names (separated with commas)
    there. Depending on your newsreader, it might or might not work. It
    will work on most non-brain-dead newsreaders. (I count Microsoft
    Outlook Express as non-brain-dead, but Google as brain-dead.)

    --
    /-- Joona Palaste () ---------------------------\
    | Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
    | http://www.helsinki.fi/~palaste W++ B OP+ |
    \----------------------------------------- Finland rules! ------------/
    "You could take his life and..."
    - Mirja Tolsa
     
    Joona I Palaste, Oct 12, 2003
    #8
  9. "Nathan" <> wrote in message news:<bmbfos$c1n$>...
    > > Hi,
    > > I've been asked in a job interview how to make C code look like C++
    > > code, and honestly I didn't know what to answer because I have never

    > really
    > > done a lot of C. Now, I've been searching around the web about web sites
    > > that talk about this subject, but I've had no luck. Can anyone point me to
    > > some web site about this subject? Thanks a lot!

    >
    > Hi,
    >
    > Do you mean you want to do object oriented programming in C? In that case,
    > there are many ways of doing this. The following article describes one way:
    > http://www.accu.org/acornsig/public/articles/oop_c.html
    >


    Or you can study the lightweight C++ preprocessor, which takes as input
    a language that looks like C++ and produces good old C.

    http://students.ceid.upatras.gr/~sxanth/lwc/index.html

    Next version has template specializations and other goodies.
     
    stelios xanthakis, Oct 12, 2003
    #9
  10. Fronsac

    Ben Pfaff Guest

    "Fronsac" <> writes:

    > I've been asked in a job interview how to make C code look like C++
    > code, and honestly I didn't know what to answer because I have never really
    > done a lot of C. Now, I've been searching around the web about web sites
    > that talk about this subject, but I've had no luck. Can anyone point me to
    > some web site about this subject? Thanks a lot!


    You could name all of your header files without .h suffixes.
    --
    "We put [the best] Assembler programmers in a little glass case in the hallway
    near the Exit sign. The sign on the case says, `In case of optimization
    problem, break glass.' Meanwhile, the problem solvers are busy doing their
    work in languages most appropriate to the job at hand." --Richard Riehle
     
    Ben Pfaff, Oct 12, 2003
    #10
  11. Fronsac wrote:

    >> You posted the same question with slightly different subject lines
    >> to (at least) a.c.l.l.c-c++ and c.l.c.

    >
    > Yeah, I was too lazy to copy-paste the subject line from the other post.


    Lazy doesn't win friends on Usenet - at least, not when the lazy person is
    the one asking for help.

    > I
    > posted in two forums just to be sure at least one person answered me. :)
    >
    >> If you feel the need to post to more than one news-group, please
    >> cross-post rather than multi-post. Thank you.

    >
    > What is cross-post? Could you explain me what it is and how to do it?


    Cross-posting is the posting of one article to more than one newsgroup
    (rather than posting two identical articles to one newsgroup each). Typical
    newsreaders allow you to do this by typing more than one group name into
    the "Groups" header when you are creating your article.

    The reason for cross-posting is that it allows newsreaders to deal
    intelligently with the thread when a reader (such as myself) subscribes to
    /both/ the newsgroups to which you have cross-posted. Having presented your
    article to me in one group, it would not bother to do so in the second,
    because it would "know" that I'd already read the article.

    When you post identical articles with separate message IDs in separate
    groups (as you did this time around), the newsreader can't legitimately
    associate them, so it doesn't. This costs your readers time. Incurring
    unnecessary costs of your readers is not a good idea when /you/ are asking
    /them/ for help.

    --
    Richard Heathfield :
    "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    K&R answers, C books, etc: http://users.powernet.co.uk/eton
     
    Richard Heathfield, Oct 12, 2003
    #11
  12. Fronsac

    Fronsac Guest

    > Cross-posting is the posting of one article to more than one newsgroup
    > (rather than posting two identical articles to one newsgroup each).

    Typical
    > newsreaders allow you to do this by typing more than one group name into
    > the "Groups" header when you are creating your article.


    Thanks a lot. I'm not sure Outlook Express does this, but Outlook is only a
    temporary solution anyway. Thanks for the info.
     
    Fronsac, Oct 12, 2003
    #12
  13. Fronsac

    Mike Wahler Guest

    "Fronsac" <> wrote in message
    news:bUjib.17268$...
    > > Cross-posting is the posting of one article to more than one newsgroup
    > > (rather than posting two identical articles to one newsgroup each).

    > Typical
    > > newsreaders allow you to do this by typing more than one group name into
    > > the "Groups" header when you are creating your article.

    >
    > Thanks a lot. I'm not sure Outlook Express does this,


    Yes, Outlook Express does handle crossposts correctly
    as far as I can tell.

    -Mike
     
    Mike Wahler, Oct 12, 2003
    #13
  14. [OT] Using Outlook Express (was: Re: Having C code looking like C++ code)

    "Fronsac" <> wrote in message
    news:bUjib.17268$...
    > > Cross-posting is the posting of one article to more than one

    newsgroup
    > > (rather than posting two identical articles to one newsgroup

    each).
    > Typical
    > > newsreaders allow you to do this by typing more than one group

    name into
    > > the "Groups" header when you are creating your article.

    >
    > Thanks a lot. I'm not sure Outlook Express does this, but Outlook is

    only a
    > temporary solution anyway. Thanks for the info.


    Outlook Express does support cross-posting. If you click "Newsgroups"
    (the icon and label, not the text-box to it's right) a dialog will
    appear. Here you can select one or more destination groups.
    Alternatively, you can type them in the text-box separated by commas,
    if you really want. If you do cross-post, you might also want to set
    up where follow-ups to your post are sent, rather than have them
    bounce around all of the groups (why have a potentially huge
    conversation appear in multiple groups?). To do this, select "All
    Headers" from the "View" menu then use the "Followup-To" section like
    the "Newgroups" section, but only add one newgroup (the most
    appropriate for your question is probably best). You can ignore the
    other sections it adds (except "Subject", of course).

    Mike

    --
    Michael Winter
    M.Winter@[no-spam]blueyonder.co.uk (remove [no-spam] to reply)
     
    Michael Winter, Oct 12, 2003
    #14
  15. Fronsac

    James Hu Guest

    On 2003-10-12, Fronsac <> wrote:
    > I've been asked in a job interview how to make C code look like C++
    > code, and honestly I didn't know what to answer because I have never
    > really done a lot of C. Now, I've been searching around the web about
    > web sites that talk about this subject, but I've had no luck. Can
    > anyone point me to some web site about this subject? Thanks a lot!


    Let's consider a simple example: providing an integer stack.

    Here's a typical way of doing it:

    +---
    | /* -- stack.h -- */
    | extern int push(int value);
    | extern int pop(int *value);
    | extern void popall(void);
    +---
    | /* -- stack.c -- */
    | #include "stack.h"
    |
    | #define MAX_STACK 100
    | static int stack[MAX_STACK];
    | static unsigned count;
    |
    | int push(int value) {
    | if (count >= MAX_STACK) return -1;
    | stack[count++] = value;
    | return 0;
    | }
    |
    | int pop(int *value) {
    | if (count == 0) return -1;
    | *value = stack[--count];
    | return 0;
    | }
    |
    | void popall(void) {
    | count = 0;
    | }
    +---

    There may be other deficiencies with this implementation, but at least
    one of them is that any application that uses this implementation is
    limited to only one stack. There are various ways of addressing this
    issue, but one of the most short sighted ways is to simply copy off
    stack.c to another file stack2.c and rename the functions push2 and
    pop2 to create a second stack.

    Better is to encapsulate the stack in a structure so that an
    application can create as many stacks as it needs without having to
    apply cut and paste coding.

    +---
    | /* -- stack.h -- */
    | #define MAX_STACK 100
    | typedef struct stacktype {
    | int stack[MAX_STACK];
    | unsigned count;
    | } stacktype;
    |
    | extern int push(stacktype *s, int value);
    | extern int pop(stacktype *s, int *value);
    | extern void popall(stacktype *s);
    +---
    | /* -- stack.c -- */
    | #include "stack.h"
    |
    | int push(stacktype *s, int value) {
    | if (s->count >= MAX_STACK) return -1;
    | s->stack[s->count++] = value;
    | return 0;
    | }
    |
    | int pop(stacktype *s, int *value) {
    | if (s->count == 0) return -1;
    | *value = s->stack[--s->count];
    | return 0;
    | }
    |
    | void popall(stacktype *s) {
    | s->count = 0;
    | }
    +---

    This implementation is sufficient for most applications needing an
    integer stack. However, another minor drawback is that all stacks
    are always of the same size. In order to avoid the cut and paste
    solution to allow different sized stacks, this property should also be
    encapsulated within the stack data structure. However, now the stack
    implementation is exposed to the extent that users of the interface must
    muck around inside the encapsulation to use the interface. In order to
    decouple the interface from the implementaiton, we make the stacktype
    opaque. The result provides a limited form of polymorphism, since
    the stack interface client need not be aware of how the stack was
    created to use the stack.

    +---
    | /* -- stack.h -- */
    | typedef struct stacktype stacktype;
    |
    | extern stacktype *create_bounded_stack(unsigned stacksize);
    | extern void destroy_stack(stacktype *s);
    |
    | extern int push(stacktype *s, int value);
    | extern int pop(stacktype *s, int *value);
    | extern void popall(stacktype *s);
    +---
    | /* -- stack.c -- */
    | #include <stdlib.h>
    | #include "stack.h"
    |
    | struct stacktype {
    | unsigned max_stack;
    | unsigned count;
    | int stack[];
    | };
    |
    | int push(stacktype *s, int value) {
    | if (s->count >= s->max_stack) return -1;
    | s->stack[s->count++] = value;
    | return 0;
    | }
    |
    | int pop(stacktype *s, int *value) {
    | if (s->count == 0) return -1;
    | *value = s->stack[--s->count];
    | return 0;
    | }
    |
    | void popall(stacktype *s) {
    | s->count = 0;
    | }
    |
    | void destroy_stack(stacktype *s) {
    | free(s);
    | }
    |
    | stacktype *create_bounded_stack(unsigned stacksize) {
    | stacktype *s;
    | if (stacksize == 0) return 0;
    | s = malloc(sizeof(stacktype) + stacksize*sizeof(int));
    | if (s != 0) {
    | s->max_stack = stacksize;
    | s->count = 0;
    | }
    | return s;
    | }
    +---

    The final point we will address is that the interface only provides
    a bounded stack implementation. Suppose an application is utilizing
    the stack in multiple modules. In some modules, the bounded stack
    is required, because it is used to throttle the work load. In other
    modules, it has been determined that a bounded stack is unacceptable,
    since pre-allocating the maximum required memory is too wasteful, and
    and the most common cases only require a small amount of memory.

    Again, one could perform cut and paste, rename the stack interfaces
    for an unbounded implementation, and alter the modules that need the
    unbounded implementation to use the new interface. However, to avoid
    the pitfalls of cut and paste programming, an alternative solution
    is to make the interface inheritable and extensible. Then, applying
    reuse on the interface, implement the unbounded stack.

    +---
    | /* -- stack.h -- */
    | typedef struct stacktype stacktype;
    | struct stacktype {
    | int (*push)(stacktype *s, int value);
    | int (*pop)(stacktype *s, int *value);
    | void (*popall)(stacktype *s);
    | void (*destroy)(stacktype *s);
    | };
    |
    | static inline int push(stacktype *s, int value) {return s->push(s, value);}
    | static inline int pop(stacktype *s, int *value) {return s->pop(s, value);}
    | static inline void popall(stacktype *s) {s->popall(s);}
    | static inline void destroy_stack(stacktype *s) {s->destroy(s);}
    +---
    | /* -- bounded_stack.h -- */
    | #include "stack.h"
    | extern stacktype *create_bounded_stack(unsigned stacksize);
    +---
    | /* -- bounded_stack.c -- */
    | #include <stdlib.h>
    | #include "bounded_stack.h"
    |
    | typedef struct bounded_stacktype {
    | stacktype interface;
    | unsigned max_stack;
    | unsigned count;
    | int stack[];
    | } bounded_stacktype;
    |
    | static int bounded_push(stacktype *s, int value) {
    | bounded_stacktype *bs = (void *)s;
    | if (bs->count >= bs->max_stack) return -1;
    | bs->stack[bs->count++] = value;
    | return 0;
    | }
    |
    | static int bounded_pop(stacktype *s, int *value) {
    | bounded_stacktype *bs = (void *)s;
    | if (bs->count == 0) return -1;
    | *value = bs->stack[--bs->count];
    | return 0;
    | }
    |
    | static void bounded_popall(stacktype *s) {
    | bounded_stacktype *bs = (void *)s;
    | bs->count = 0;
    | }
    |
    | static void destroy_bounded_stack(stacktype *s) {
    | free(s);
    | }
    |
    | static const stacktype bounded_stack_interface = {
    | bounded_push,
    | bounded_pop,
    | bounded_popall,
    | destroy_bounded_stack,
    | };
    |
    | stacktype *create_bounded_stack(unsigned stacksize) {
    | bounded_stacktype *bs;
    | if (stacksize == 0) return 0;
    | bs = malloc(sizeof(bounded_stacktype) + stacksize*sizeof(int));
    | if (bs == 0) return 0;
    | bs->interface = bounded_stack_interface;
    | bs->max_stack = stacksize;
    | bs->count = 0;
    | return &bs->interface;
    | }
    +---
    | /* -- unbounded_stack.h -- */
    | #include "stack.h"
    | extern stacktype *create_unbounded_stack(void);
    +---
    | /* -- unbounded_stack.c -- */
    | #include <stdlib.h>
    | #include "unbounded_stack.h"
    | #include "bounded_stack.h"
    |
    | #define UB_STACK_DEFAULT 100
    | static unsigned UB_STACK_SIZE = UB_STACK_DEFAULT;
    |
    | typedef struct unbounded_substacktype {
    | struct unbounded_substacktype *link;
    | stacktype *substack;
    | } unbounded_substacktype;
    |
    | static unbounded_substacktype *create_unbounded_substack(void) {
    | unbounded_substacktype *s;
    | s = malloc(sizeof(unbounded_substacktype));
    | if (s == 0) return 0;
    | s->substack = create_bounded_stack(UB_STACK_SIZE);
    | if (s->substack == 0) {
    | free(s);
    | return 0;
    | }
    | s->link = 0;
    | return s;
    | }
    |
    | static void destroy_unbounded_substack(unbounded_substacktype *s) {
    | destroy_stack(s->substack);
    | free(s);
    | }
    |
    | typedef struct unbounded_stacktype {
    | stacktype interface;
    | unbounded_substacktype *current_stack;
    | unbounded_substacktype *free_stack;
    | } unbounded_stacktype;
    |
    | static int unbounded_push(stacktype *s, int value) {
    | unbounded_stacktype *us = (void *)s;
    | unbounded_substacktype *cs = us->current_stack;
    | unbounded_substacktype *fs;
    | if (cs == 0 || push(cs->substack, value) == -1) {
    | fs = us->free_stack;
    | if (fs == 0) {
    | if ((fs = create_unbounded_substack()) == 0) return -1;
    | } else us->free_stack = 0;
    | fs->link = cs;
    | cs = us->current_stack = fs;
    | return push(cs->substack, value);
    | }
    | return 0;
    | }
    |
    | static int unbounded_pop(stacktype *s, int *value) {
    | unbounded_stacktype *us = (void *)s;
    | unbounded_substacktype *cs = us->current_stack;
    | unbounded_substacktype *fs;
    | if (cs == 0) return -1;
    | if (pop(cs->substack, value) == -1) {
    | fs = cs;
    | cs = us->current_stack = cs->link;
    | if (us->free_stack == 0) us->free_stack = fs;
    | else destroy_unbounded_substack(fs);
    | return pop(cs->substack, value);
    | }
    | return 0;
    | }
    |
    | static void unbounded_popall(stacktype *s) {
    | unbounded_stacktype *us = (void *)s;
    | unbounded_substacktype *cs = us->current_stack;
    | unbounded_substacktype *fs = us->free_stack;
    | if (cs == 0) return;
    | if (fs == 0) {
    | fs = us->free_stack = cs;
    | cs = us->current_stack = cs->link;
    | fs->link = 0;
    | popall(fs->substack);
    | }
    | while (cs != 0) {
    | cs = cs->link;
    | destroy_unbounded_substack(us->current_stack);
    | us->current_stack = cs;
    | }
    | }
    |
    | static void destroy_unbounded_stack(stacktype *s) {
    | unbounded_stacktype *us = (void *)s;
    | unbounded_popall(s);
    | if (us->free_stack) destroy_unbounded_substack(us->free_stack);
    | free(s);
    | }
    |
    | static const stacktype unbounded_stack_interface = {
    | unbounded_push,
    | unbounded_pop,
    | unbounded_popall,
    | destroy_unbounded_stack,
    | };
    |
    | stacktype *create_unbounded_stack(void) {
    | unbounded_stacktype *us;
    | us = malloc(sizeof(unbounded_stacktype));
    | if (us == 0) return 0;
    | us->interface = unbounded_stack_interface;
    | us->current_stack = 0;
    | us->free_stack = 0;
    | return &us->interface;
    | }
    +---

    The final example shows an extensible polymorphic interface in C. The
    interface is exposed in an object that can be inherited. The example
    leverages the inheritance to provide multiple implementations of the
    interface. Code utilizing the interface can be simultaneously reused to
    manipulate either a bounded or unbounded stack. Code can furthermore
    inherit the interface and provide their own implementations.

    This is of course only an example, and the techniques applied here is
    arguably overkill for such a simple data structure. The simplicity,
    however, allows the techniques to be illustrated in a relatively
    straight forward and compact manner. These techniques here are nothing
    new to the experienced software professional. They will be found in OS
    kernel code, I/O interface APIs, protocol stacks, GUI APIs, and many
    other places.

    -- James
     
    James Hu, Oct 13, 2003
    #15

  16. > Or you can study the lightweight C++ preprocessor, which takes as input
    > a language that looks like C++ and produces good old C.


    AHEM... although I think it's really interesting and I've successfully
    used it, given something like

    my_var_ptr = new myclass(param);

    you get

    my_var_ptr = (
    { struct myclass*InTeRnAl_y = (struct myclass *)malloc(sizeof(struct
    myclass));
    myclass_ctor(InTeRnAl_y, param);
    InTeRnAl_y; } );

    I think this should be instead

    struct myclass *InTeRnAl_y = malloc(sizeof(struct myclass));
    my_var_ptr = InTeRnAl_y
    myclass_ctor(InTeRnAl_y, param);

    Not to mention some gcc extensions like

    static void GlObALcOnStRuCtOr ( )
    {
    }
    static void (*_Counter_cppAsCiiArT)(void) __attribute__ ((unused,__section__
    (".ctors"))) = GlObALcOnStRuCtOr;

    appended to every source "translated"...

    Ah... and you can't compile the sources without gcc... (plus cygwin on
    Windows..).

    PS: Anyway I've supported it from the start ^^
     
    Lorenzo Villari, Oct 14, 2003
    #16
  17. Fronsac wrote:

    > I've been asked in a job interview how to make C code look like C++
    > code, and honestly I didn't know what to answer because I have never really
    > done a lot of C. Now, I've been searching around the web about web sites
    > that talk about this subject, but I've had no luck.



    $ cat Point.h
    #ifndef _Point_h
    #define _Point_h 1

    typedef struct {
    /* representation */
    double X;
    double Y;
    } Point;
    /* functions */
    double
    xPoint(const Point *p);
    double
    yPoint(const Point *p);
    /* constructors */
    Point
    createDefaultPoint(void);
    Point
    createExplicitPoint(double x, double y);
    /* destructor */
    void
    destroyPoint(Point* p);

    #endif /* _Point_h */

    $ cat Point.c
    /* gcc -I. -O2 -c Point.c
    */
    #include<Point.h>

    /* functions */
    double
    xPoint(const Point *p) {
    return p->X; }
    double
    yPoint(const Point *p) {
    return p->Y; }
    /* constructors */
    Point
    createDefaultPoint(void) {
    Point p;
    p.X = 0.0;
    p.Y = 0.0;
    return p; }
    Point
    createExplicitPoint(double x, double y) {
    Point p;
    p.X = x;
    p.Y = y;
    return p;
    }
    /* destructor */
    void
    destroyPoint(Point* p) { }

    $ cat Color.h
    #ifndef _Color_h
    #define _Color_h 1
    typedef struct {
    unsigned char R; /* red */
    unsigned char G; /* green */
    unsigned char B; /* blue */
    } Color;
    /* functions */
    unsigned int
    redColor(const Color *c);
    unsigned int
    greenColor(const Color *c);
    unsigned int
    blueColor(const Color *c);
    /* constructors */
    Color
    createDefaultColor(void);
    Color
    createExplicitColor(
    unsigned int r,
    unsigned int g,
    unsigned int b);
    /* destructor */
    void
    destroyColor(Color *c);

    #endif /* _Color_h */

    $ cat Color.c
    /* gcc -I. -O2 -c Color.c
    */
    #include<Color.h>

    /* functions */
    unsigned int
    redColor(const Color *c) {
    return c->R; }
    unsigned int
    greenColor(const Color *c) {
    return c->G; }
    unsigned int
    blueColor(const Color *c) {
    return c->B; }
    /* constructors */
    Color
    createDefaultColor(void) {
    Color c;
    c.R = 0;
    c.G = 0;
    c.B = 0;
    return c; }
    Color
    createExplicitColor(
    unsigned int r,
    unsigned int g,
    unsigned int b) {
    Color c;
    c.R = r;
    c.G = g;
    c.B = b;
    return c; }
    /* destructor */
    void
    destroyColor(Color *c) { }

    $ cat Shape.h
    #ifndef _Shape_h
    #define _Shape_h 1

    #include<Point.h>
    #include<Color.h>

    typedef void* virtual_t;
    typedef struct {
    Point P; /* first public base class */
    Color C; /* second public base class */
    virtual_t* V; /* virtual function table */
    } Shape;
    /* functions */
    Point*
    pointShape(Shape* s);
    Color*
    colorShape(Shape* s);
    void
    drawShape(const Shape *s);
    void
    drawGeneralShape(const Shape *s);
    double
    areaShape(const Shape *s);
    double
    areaGeneralShape(const Shape *s);
    /* constructors */
    Shape
    createDefaultShape(void);
    Shape
    createExplicitShape(
    const Point *p,
    const Color *c);
    /* destructor */
    void
    destroyShape(Shape *s);

    #endif /* _Shape_h */

    $ cat Shape.c
    /* gcc -I. -O2 -c Shape.c
    */
    #include<stdio.h>
    #include<Shape.h>

    typedef void (*drawShape_t)(const Shape *);
    typedef double (*areaShape_t)(const Shape *);
    /* functions */
    Point*
    pointShape(Shape* s) {
    return &(s->P); }
    Color*
    colorShape(Shape* s) {
    return &(s->C); }
    void
    drawGeneralShape(const Shape *s) {
    fprintf(stderr, "drawShape(const Shape *s)\n");
    fflush(stderr); }
    double
    areaGeneralShape(const Shape *s) {
    fprintf(stderr, "areaShape(const Shape *s)\n");
    fflush(stderr);
    return 0.0; }
    static virtual_t
    vtableShape[] = {(virtual_t)drawGeneralShape,
    (virtual_t)areaGeneralShape};
    void
    drawShape(const Shape *s) {
    ((drawShape_t)(s->V[0]))(s); }
    double
    areaShape(const Shape *s) {
    return ((areaShape_t)(s->V[1]))(s); }
    /* constructors */
    Shape
    createDefaultShape(void) {
    Shape S;
    S.P = createDefaultPoint();
    S.C = createDefaultColor();
    S.V = vtableShape;
    return S; }
    Shape
    createExplicitShape(
    const Point *p,
    const Color *c) {
    Shape S;
    S.P = *p;
    S.C = *c;
    S.V = vtableShape;
    return S; }
    /* destructor */
    void
    destroyShape(Shape *s) {
    destroyColor(colorShape(s));
    destroyPoint(pointShape(s));
    }

    $ cat Circle.h
    #ifndef _Circle_h
    #define _Circle_h 1

    #include<Shape.h>

    typedef struct {
    Shape S; /* public base class */
    double R; /* radius */
    } Circle;
    /* functions */
    Shape*
    shapeCircle(Circle* c);
    double
    radiusCircle(const Circle* c);
    void
    drawCircle(const Circle *c);
    double
    areaCircle(const Circle *c);
    /* constructors */
    Circle
    createDefaultCircle(void);
    Circle
    createExplicitCircle(const Shape *s, double r);
    /* destructor */
    void
    destroyCircle(Circle *c);

    #endif /* _Circle_h */

    $ cat Circle.c
    /* gcc -I. -O2 -c Circle.c
    */
    #include<math.h>
    #include<stdio.h>
    #include<Circle.h>

    typedef void (*drawCircle_t)(const Circle *);
    typedef double (*areaCircle_t)(const Circle *);
    /* functions */
    Shape*
    shapeCircle(Circle* c) {
    return &(c->S); }
    double
    radiusCircle(const Circle* c) {
    return c->R; }
    void
    drawCircle(const Circle *c) {
    fprintf(stderr, "drawCircle(const Circle *c)\n");
    fflush(stderr); }
    double
    areaCircle(const Circle *c) {
    const
    double pi = 3.14159265358979323846;
    double r = radiusCircle(c);
    fprintf(stderr, "areaCircle(const Circle *c)\n");
    fflush(stderr);
    return pi*r*r; }
    static virtual_t
    vtableCircle[] = {(virtual_t)drawCircle,
    (virtual_t)areaCircle};
    /* constructors */
    Circle
    createDefaultCircle(void) {
    Circle C;
    C.S = createDefaultShape();
    C.R = 0.0;
    C.S.V = vtableCircle;
    return C; }
    Circle
    createExplicitCircle(const Shape *s, double r) {
    Circle C;
    C.S = *s;
    C.R = r;
    C.S.V = vtableCircle;
    return C; }
    /* destructor */
    void
    destroyCircle(Circle *c) {
    destroyShape(shapeCircle(c));
    }

    $ cat main.c
    /* gcc -I. -O2 -o main main.c Circle.o Shape.o Color.o Point.o
    */
    #include<stdio.h>
    #include<Circle.h>

    int
    main(int argc, char* argv[]) {
    Shape s = createDefaultShape();
    Circle c = createExplicitCircle(&s, 2.0);
    drawShape((Shape*)(&c));
    fprintf(stdout, "%g = radius\t %g = area\n",
    radiusCircle(&c), areaShape((Shape*)(&c)));
    return 0;
    }

    $ cat Makefile
    CC=gcc
    DEFINES=
    INCLUDE=-I.
    OPTIONS=-O2
    LIBRARY=
    OBJECTS=Point.o Color.o Shape.o Circle.o
    SOURCES=Point.c Color.c Shape.c Circle.c
    HEADERS=Point.h Color.h Shape.h Circle.h
    library=
    COMPILE=$(CC) $(DEFINES) $(INCLUDE) $(LIBRARY) $(OPTIONS)

    main: $(HEADERS) $(OBJECTS) main.c
    $(COMPILE) -o main main.c $(OBJECTS) $(library)

    Point.o: Point.h Point.c
    $(COMPILE) -c Point.c

    Color.o: Color.h Color.c
    $(COMPILE) -c Color.c

    Shape.o: Shape.h Shape.c
    $(COMPILE) -c Shape.c

    Circle.o: Circle.h Circle.c
    $(COMPILE) -c Circle.c

    clean:
    rm $(OBJECTS) main
     
    E. Robert Tisdale, Oct 14, 2003
    #17
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. UnixUser
    Replies:
    1
    Views:
    342
    Irrwahn Grausewitz
    Dec 15, 2003
  2. Patrick Kowalzick
    Replies:
    5
    Views:
    479
    Patrick Kowalzick
    Mar 14, 2006
  3. Frank Kurka
    Replies:
    8
    Views:
    314
  4. Mark
    Replies:
    9
    Views:
    178
    Patrick Hurley
    Mar 10, 2006
  5. Mmcolli00 Mom
    Replies:
    7
    Views:
    114
    Jean-Denis Muys
    Feb 6, 2009
Loading...

Share This Page