Assorted questions from a C++ programmer

Discussion in 'C Programming' started by V.Ch., May 10, 2005.

  1. V.Ch.

    V.Ch. Guest

    In near future I can face a prospect of writing some stuff in C. Being a
    C++ programmer, I've got practically no experience in C. I'd be obliged
    if someone could answer the following questions (from specific to more
    general):

    1. Having looked though some C sources I was horrified by the number of
    macros. E.g., what could be the purpose of using this:

    #define CFG_REF(c, f) ((c) -> f)
    #define SERVER_ADDRESS(c) CFG_REF (c, server_address)


    From the point of view of C++ coding, this would seem quite idiotic
    (why not use -> operator directly?!). But I've got reasons to believe
    that the guy who wrote this is a good C coder.

    2. If you were to write some program that can potentially be compiled on
    a number of platforms by different compilers, how would you declare
    automatic variables? Does it pay of to be extra conservative and don't
    assume that every compiler now supports C99 with respect to declaring
    variables wherever you want? Personally, I find it not only tiresome,
    but actually very bad to declare all the variables at the beginning of a
    block. But then again, I am not a C programmer. Is there any consensus
    here?

    3. What are the ways to structure large programs? I am falling back to
    C++ again, thinking about object-oriented programming in C (something
    like fopen, fread/fwrite and fclose) and emulating VTBL interfaces with
    vectors of function pointers. Any other aproaches here? Any
    links/tutorials would be very welcome.

    4. Any other links and suggestions that would be useful for a C++
    programmer that has to write in C.
     
    V.Ch., May 10, 2005
    #1
    1. Advertising

  2. In article <d5r3ug$1v6t$>, V.Ch. <> wrote:
    >I'd be obliged
    >if someone could answer the following questions (from specific to more
    >general):


    >1. Having looked though some C sources I was horrified by the number of
    >macros. E.g., what could be the purpose of using this:


    >#define CFG_REF(c, f) ((c) -> f)
    >#define SERVER_ADDRESS(c) CFG_REF (c, server_address)


    Hiding of implementation. The data structure could be completely
    replaced, possibly by functions, with very little change to the code.


    >2. If you were to write some program that can potentially be compiled on
    >a number of platforms by different compilers, how would you declare
    >automatic variables? Does it pay of to be extra conservative and don't
    >assume that every compiler now supports C99 with respect to declaring
    >variables wherever you want?


    Yes, it does pay. Actual C99 implementations are rare -- at least
    ones that support the full library. Without the full library, it is
    in effect "C89 plus extensions and some bugs", and as soon as you
    start down the "extensions" path you are sure to lose portability.


    >3. What are the ways to structure large programs?


    Many different ways, depending on what you are trying to achieve
    and what the natural problem decomposition is.

    I've even heard of people who believe that every source file should
    have at most one function... but that requires exposing private data
    structures.

    >I am falling back to
    >C++ again, thinking about object-oriented programming in C (something
    >like fopen, fread/fwrite and fclose) and emulating VTBL interfaces with
    >vectors of function pointers. Any other aproaches here? Any
    >links/tutorials would be very welcome.


    What domain of problem are you trying to deal with? Unless you
    have the same kind of operations being performed on a number of
    ideologically similar but not identicially-structured objects, the VTBL
    approach is probably a waste.

    Above, was the reference to fopen etc. along the lines that you were
    planning to do the equivilent of smalltalk's [self print]
    in which arbitrary objects might get juggled around but you need to
    be able to tell them to pretty-print themselves? Or are you working
    with something like a graphics package where you want to be able
    manipulate a number of different kinds of objects, and you want it
    to be extensible without changing the draw code, just by implementing
    new objects? [If so, then one approach that can work is to
    have each object type call "registration" routines, with
    the function pointers kept track of (one per -type- per functionality).
    The routine that needs to invoke variable behaviour then searches
    its registry table by type number and calls the associated function
    pointer on the object.
    --
    'The short version of what Walter said is "You have asked a question
    which has no useful answer, please reconsider the nature of the
    problem you wish to solve".' -- Tony Mantler
     
    Walter Roberson, May 10, 2005
    #2
    1. Advertising

  3. V.Ch.

    V.Ch. Guest

    Walter Roberson wrote:
    > Yes, it does pay. Actual C99 implementations are rare -- at least
    > ones that support the full library.


    I am not interested much in anything else than variable declaration
    part. Are you saying that I cannot rely even on that?

    > What domain of problem are you trying to deal with?


    Well, for now I am not going to touch anything big - just an Apache
    module. I don't think it will need any king of structure :). The
    question about structuring a big program was less practical (at least
    for now), I asked it mainly out of quriosity.

    > Above, was the reference to fopen etc. along the lines that you were
    > planning to do the equivilent of smalltalk's [self print]
    > in which arbitrary objects might get juggled around but you need to
    > be able to tell them to pretty-print themselves?


    Don't know anything about smalltalk. What I meant was quite simple
    actually, that instead of a C++ class I would create a C module in which I:

    1. Declare a struct to hold state variables of an "object" (FILE)
    2. "Constructor" - function that creates an object and returns a
    "handle" (fopen).
    3. "Methods" - functions that take this "handle" as a parameter
    (fread/fwrite).
    4. "Destructor" (fclose)
     
    V.Ch., May 10, 2005
    #3
  4. V.Ch.

    Eric Sosman Guest

    V.Ch. wrote:
    > In near future I can face a prospect of writing some stuff in C. Being a
    > C++ programmer, I've got practically no experience in C. I'd be obliged
    > if someone could answer the following questions (from specific to more
    > general):


    First, read Walter Roberson's response; I'm just tossing
    in a few minor additions.

    > 2. If you were to write some program that can potentially be compiled on
    > a number of platforms by different compilers, how would you declare
    > automatic variables? Does it pay of to be extra conservative and don't
    > assume that every compiler now supports C99 with respect to declaring
    > variables wherever you want? Personally, I find it not only tiresome,
    > but actually very bad to declare all the variables at the beginning of a
    > block. But then again, I am not a C programmer. Is there any consensus
    > here?


    In C90 a block's variable declarations must precede all
    its executable statements. However, blocks can nest to give
    you a partial simulation of what you're looking for:

    int func(int arg) {
    int a; /* "function global" */
    ...
    {
    double x; /* "block local" */
    ...
    }
    ...
    {
    char x[100]; /* nothing to do with prior `x' */
    ...
    }
    ...
    return 42;
    }

    You can even recycle a "current" identifier in a nested block,
    but I'd avoid it -- can you spell "maintenance nightmare?"

    Whether it's burdensome to park the variable declarations
    at the start of a function depends on how many variables there
    are. If you've got a Whole Lot of local variables and they
    don't belong to a few tightly-related groups, it may be time
    to think about splitting up the function. Small functions
    improve manageability, and at the same time they tend to keep
    the population of local variables under control.

    > 3. What are the ways to structure large programs? I am falling back to
    > C++ again, thinking about object-oriented programming in C (something
    > like fopen, fread/fwrite and fclose) and emulating VTBL interfaces with
    > vectors of function pointers. Any other aproaches here? Any
    > links/tutorials would be very welcome.


    If you want to write C++ programs, write them in C++ and
    don't try to "port your language" to C. A programmer who
    insists on writing "C-ish" code for a C++ environment is
    usually making a mistake; the reverse is equally mistaken.
    Seek C-ish solutions; don't try to bend C into a poor man's
    version of C++. You'll wind up with something that's neither
    fish nor fowl, a feathered fish that neither swims nor flies.

    "A Real Programmer can write FORTRAN in any language."

    --
     
    Eric Sosman, May 10, 2005
    #4
  5. "V.Ch." <> writes:
    > Walter Roberson wrote:
    >> Yes, it does pay. Actual C99 implementations are rare -- at least
    >> ones that support the full library.

    >
    > I am not interested much in anything else than variable declaration
    > part. Are you saying that I cannot rely even on that?


    Right, you can't rely on being able to mix declarations and statements
    if you want your C to be completely portable. It's likely to work on
    a number of systems, but you could later need to port the code to a
    system that doesn't have a C compiler that supports this C99 feature.

    You can, of course, reduce the scope of a variable by creating a
    block:

    void foo(void)
    {
    int x;
    statement;
    statement;
    {
    int y;
    statement;
    statement;
    }
    }

    If this causes the nesting level to become uncomfortably deep, you can
    either declare everything at the top of the function or consider that
    your function might be too big.

    On the other hand, if you're not concerned about absolute portability,
    you might be able to get away with mixing declarations and statements.
    For example, if you can count on every system your code might run on
    to have a sufficiently recent version of gcc, you can use gcc
    extensions. (Note that gcc extensions, other than the ones that are
    part of C99, are off-topic here.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, May 10, 2005
    #5
  6. In article <d5r7ft$21et$>, V.Ch. <> wrote:
    >I am not interested much in anything else than variable declaration
    >part. Are you saying that I cannot rely even on that?


    For clarity: are you refering to the ability to declare variables
    where convenient, or are you refering to variable-length arrays?

    There are still quite a number of compilers that are C89 without
    any ability to declare variables in convenient places. Variable-length
    arrays are less common.

    You could restrict yourself to gcc4, which I believe supports both
    features. Generally speaking, you really have to be disciplined when
    you program in gcc, as they tend to throw in extensions without
    making it clear that they are extensions.

    Historically, gcc has had issues with silently accepting non-portable
    code even when warnings were turned on: their excuse has been along the
    lines of, "The ANSI standards only bind compilers that claim compliance
    with the standard. Since we don't claim compliance with the standard,
    we are free to ignore any part of the standard we want, and free to
    implement extensions without warning that they are extensions."

    >> What domain of problem are you trying to deal with?


    >What I meant was quite simple
    >actually, that instead of a C++ class I would create a C module in which I:


    >1. Declare a struct to hold state variables of an "object" (FILE)
    >2. "Constructor" - function that creates an object and returns a
    >"handle" (fopen).
    >3. "Methods" - functions that take this "handle" as a parameter
    >(fread/fwrite).
    >4. "Destructor" (fclose)


    Apache (the original) at least [don't know about Apache2] wasn't
    written in that kind of style, so it might be a bit much to expect
    other people to adopt that style to use your module.

    IMHO, there isn't a lot of point in adopting a class-like structure
    for those functions, not unless you plan to write a -number- of different
    apache modules and want them all to have the same interface.
    Just do what everyone else does and use routine names that are
    module specific. The users will call the routine with the right name
    and you won't have to keep function pointers around.

    Sometimes it is useful to have a data structure with important state
    information: I'm not discouraging that, I'm just indicating that
    -likely- in the context you describe, there would not be much point
    in storing function pointers, as they would probably always be the -same-
    function pointer.
    --
    This signature intentionally left... Oh, darn!
     
    Walter Roberson, May 10, 2005
    #6
  7. V.Ch.

    CBFalconer Guest

    "V.Ch." wrote:
    >
    > In near future I can face a prospect of writing some stuff in C.
    > Being a C++ programmer, I've got practically no experience in C.
    > I'd be obliged if someone could answer the following questions
    > (from specific to more general):
    >

    .... snip ...
    >
    > 3. What are the ways to structure large programs? I am falling
    > back to C++ again, thinking about object-oriented programming
    > in C (something like fopen, fread/fwrite and fclose) and
    > emulating VTBL interfaces with vectors of function pointers.
    > Any other aproaches here? Any links/tutorials would be very
    > welcome.


    I suggest you take a look at the structure and interface of my
    hashlib package, for what I (for some reason) consider good C
    code. You probably need read no more than the .h and .c files.
    They are to be found in:

    <http://cbfalconer.home.att.net/download/hashlib.zip>

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
     
    CBFalconer, May 11, 2005
    #7
  8. V.Ch.

    Malcolm Guest

    "Eric Sosman" <> wrote
    > A programmer who
    > insists on writing "C-ish" code for a C++ environment is
    > usually making a mistake; the reverse is equally mistaken.
    >

    You certainly often see C++ programs which are horrible kludges, and would
    have been much better in C.

    However I would disagree on "C++ish" C.
    In C it is often a good idea to have objects, with contructors and matching
    destructors. So if I want a logical regression tree, I declare a structure,
    then I declare a function called "logictree()" which creates one, and a
    function called "killlogictree()" which destroys it when I am finished. Then
    I have a function called ltree_predict() which takes a tree and some
    observations as parameters, and predicts the class.

    What C is not good at is allowing objects to enter into relationships with
    each other. If I decide I want a general class of "logic trees", and a
    "nand-only" tree as a special case and a "balanced logic tree" as another
    special case, I cannot easily represent that program design using C, and I
    am better off with another language.
     
    Malcolm, May 12, 2005
    #8
  9. V.Ch.

    Eric Sosman Guest

    Malcolm wrote:

    > "Eric Sosman" <> wrote
    >
    >>A programmer who
    >>insists on writing "C-ish" code for a C++ environment is
    >>usually making a mistake; the reverse is equally mistaken.
    >>

    >
    > You certainly often see C++ programs which are horrible kludges, and would
    > have been much better in C.
    >
    > However I would disagree on "C++ish" C.
    > In C it is often a good idea to have objects, with contructors and matching
    > destructors. [...]


    Object-oriented design is a fine thing (in some problem
    areas, anyhow), and I have no quarrel with it -- use it m'self
    on occasion, ayeh, that I dew.

    But the O.P. was talking about "emulating VTBL interfaces
    with vectors of function pointers." This is an attempt to graft
    the implementation techniques of one language into the body of
    another, whose immune systems are likely to kick up all kinds of
    ruckus. If he wants VTBL-ish implementation artifacts, I still
    maintain he's better off seeking them in C++ than trying to emulate
    them in C. One might as well translate C to Lisp by writing a
    defun() for malloc() ... Again I repeat the Immortal Words:

    "A Real Programmer can write FORTRAN in any language."

    Don't spread jam with a meat cleaver; don't quarter a
    chicken with a butterknife. Both tasks are possible; neither
    would be pleasant.

    --
    Eric Sosman
    lid
     
    Eric Sosman, May 12, 2005
    #9
    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. Replies:
    24
    Views:
    652
    jeffc
    Oct 24, 2003
  2. John Perks and Sarah Mount

    Assorted JNI questions

    John Perks and Sarah Mount, Oct 2, 2005, in forum: Java
    Replies:
    5
    Views:
    1,286
    Roedy Green
    Oct 6, 2005
  3. Replies:
    24
    Views:
    627
    jeffc
    Oct 24, 2003
  4. Replies:
    26
    Views:
    639
    jeffc
    Oct 24, 2003
  5. Bill Atkins

    Assorted Ruby/Tk Questions/Comments

    Bill Atkins, Apr 7, 2004, in forum: Ruby
    Replies:
    1
    Views:
    159
    Hidetoshi NAGAI
    Apr 8, 2004
Loading...

Share This Page