C code in C++ and used inside class

Discussion in 'C++' started by cognacc@, Aug 4, 2009.

  1. cognacc@

    cognacc@ Guest

    Im trying to use some C code inside a C++ class, this class is used
    in another C++ class ofcourse, or will be.
    The C++ class will contain a data structure
    from the C code amongst others.

    But in the C code header file where the datatype is defined, there are
    also some global variables defined.
    Is there a way to avoid multiple inclusion error, without changing the
    C code?

    Michael
     
    cognacc@, Aug 4, 2009
    #1
    1. Advertising

  2. cognacc@

    Francesco Guest

    On 4 Ago, 19:21, "cognacc@" <> wrote:
    > Im trying to use some C code inside a C++ class, this class is used
    > in another C++ class ofcourse, or will be.
    > The C++ class will contain a data structure
    > from the C code amongst others.
    >
    > But in the C code header file where the datatype is defined, there are
    > also some global variables defined.
    > Is there a way to avoid multiple inclusion error, without changing the
    > C code?
    >
    > Michael


    Hi Michael,
    just the two cents of an hobbyist <-- assume this disclaimer of mine,
    first of all.

    If you get multiple inclusion error, I suppose that the globals
    defined in the C header are outside of the #ifndef / #define / #endif
    block of macros (assuming such macros are there).

    If your statement "without changing the C code" means that you don't
    want to touch the C header *at all*, I suppose there is no way to
    avoid such a multiple-inclusion risk (at least, not as long as other
    people is involved in coding it) otherwise you could simply add a
    further block of conditional macros wrapping the header's content -
    quite easy to automate too, in case you've got many of such
    "problematic" headers to include.

    I think that giving more details will raise more interest in your
    issue. You could post some code to illustrate it better (the C header
    in particular). Then maybe some of the more experienced could jump in.

    Have good time coding,
    cheers,
    Francesco
     
    Francesco, Aug 4, 2009
    #2
    1. Advertising

  3. cognacc@

    cognacc Guest

    On Aug 4, 9:49 pm, Victor Bazarov <> wrote:
    > cognacc@ wrote:
    > > Im trying to use  some C code inside a C++ class, this class is used
    > > in another C++ class ofcourse, or will be.
    > > The C++ class will contain a  data structure
    > > from the C code amongst others.

    >
    > > But in the C code header file where the datatype is defined, there are
    > > also some global variables defined.

    >
    > That's A VERY BAD IDEA(tm).  Variables should never be *defined* in headers.


    I mean declared sorry. if in header:
    int Ggloabalvar; // this is a declaration right


    s_57_defs.h this is the file with a few globals vars
    and also a datatype conversion, works fine compiled as C.
    -----------------------------------------------------------------------------
    #ifndef _S_57_DEFS_H
    #define _S_57_DEFS_H

    /*
    * File: s_57_defs.h
    * Author: run
    *
    * Created on March 10, 2009, 3:07 PM
    */


    #ifdef __cplusplus
    extern "C" {
    #endif

    #include <sys/queue.h>

    typedef char octet;

    typedef char tag[5]; //! \todo ? check this typedef, see page 146 k&r

    // Leader is 24 octets (bytes long) both DDR an DR leader (S-57)
    #define LEADER_SIZE 24

    // Fieldtag size ie VRID, is 4 octets long, specified int S-57
    #define FIELD_TAG_SIZE 4

    // SHOULD Probably read this and check, but not now
    // field RP 09
    #define DDR_FIELD_CONTROL_LENGTH 9

    // See iso8211 table 1 delimiter and their uses
    // Unit terminator : printable '&' : Terminates a unit in a field
    #define UT 0x1F // dec: 31 oct: \037

    // Field terminator : printable ';' : Terminates a complete field(ex:
    VRID)
    #define FT 0x1E // dec: 30 oct: \036
    // This could be defined for each field (vrid, frid etc.)


    #define STD_SIZE_LEN 220

    struct GNAME {int len; char val[10];};

    //
    ===============================================================================
    // global variables for conversion between octets to datatypes

    // bXY : X is signednes Y is width in octets
    unsigned char S57TYPE_b11; // UNSIGNED ONE OCTET CHAR
    signed char S57TYPE_b21; // SIGNED ONE OCTET UNSIGNED CHAR
    unsigned short S57TYPE_b12; // UNSIGNED TWO OCTET UNSIGNED CHAR
    signed short S57TYPE_b22; // SIGNED TWO OCTET SIGNED CHAR
    unsigned long S57TYPE_b14; //
    signed long S57TYPE_b24; //

    unsigned char S57TYPE_B5[5];
    unsigned char S57TYPE_B8[8];
    unsigned char S57TYPE_B[20]; // any large enough number
    // DUMMY just to shut compiler up

    char S57TYPE_A[200];
    char S57TYPEA_UL[200]; // ascii unspecified length
    char S57TYPEA_L8[8]; // which lengths

    char S57TYPE_I[200]; // type i of generic legnth, real
    length seen at data read time

    double S57TYPE_R; // \note correct S57TYPE long ?
    - think its incorrect!?

    int LENGTH_TYPESIZE; // length to send as
    parameter to function

    // User defined define a head of a new queue
    // Should define a tailqueue , a new call to getRecordSet() will reuse
    same queue

    TAILQ_HEAD(tailhead, DR_Data) dr_head;

    typedef struct DR_Data // DR_Data is tag
    {
    char fieldtagname[5]; // the tagname, like VRID FOID DSSI, can be
    used to look at the S57TYPE (if NAME = cast S57TYPE)
    //BOOL is_toplevel; // is a toplevel field (ex: VRID)
    int is_toplevel;
    // record numbers used for debugging data structures
    int dr_rec_nr; // total records ie FIELD numbers

    int dr_toplevel_nr; // top level FIELDS (VRID, FOID, DSID, DSSI, ..)
    number of toplevel fields, called a "RECORD BLOCK"
    int dr_repeat_nr; // repeating fields number, same fields repeating
    count
    // int dr_different_fields // total fields exclusive repeating
    fields (counted once)
    //-----------------
    void *field_ptr; // void pointer to a field a HUGE case for
    casting to field S57TYPE (or look out for aut5o generating)
    struct DR_Data *next_data; // DR_Data is tag
    // LIST struct list_head somename see man queue (LIST*)
    TAILQ_ENTRY(DR_Data) dr_data_list;
    }DR_Data; // DR_Data i typedef

    //typedef _dr_data DR_Data;

    DR_Data *dr_data_ptr, *dr_data_pnext, *dr_data_pprev;

    struct tailhead *pos_data, *q_data, *dr_head_ptr;

    void usage(char **arg);

    // DR_Data *
    int readRecordSet(char * s57_filename);

    void queue_init(void);

    #ifdef __cplusplus
    }
    #endif


    #endif /* _S_57_DEFS_H */
    -----------------------------------------------------------------------

    > > Is there a way to avoid multiple inclusion error, without changing the
    > > C code?

    > You could try creating another header with double inclusion guards and
    > include that C header there, but it looks like you'd be better off
    > rewriting the C stuff to make it proper.


    Double inclusion guards? how?

    Here is a C++ file using the data structure:
    DR_Data *genericDRData; is the type from C i need to use in my class
    ---
    #ifndef CHARTINFO_H
    #define CHARTINFO_H

    #include <string>

    extern "C"
    {
    #include <stdlib.h>
    #include <assert.h>

    #include "../../decode_seacharts/s_57_defs.h" // <---- header with
    datatype and global var, we only use the type(s)
    }

    // inner struct / class
    // latitude and longtiude coordinates
    struct LatLon
    {
    signed long lat; // Latitude
    signed long lon; // Longtitude
    };

    struct XYPos
    {
    int lat; // Latitude
    int lon; // Longtitude
    char * unit; // m or km // define domains ?
    };

    class ChartInfo
    {
    public:
    ChartInfo();

    void loadRecordSet(char *filename);
    long long getLNAME_id(); // RCNM '+' RCID
    long long getNAME_id();
    signed long getLattitude();
    signed long getLongtitude();
    int translateLatLon_to_meters(struct LatLon ll);
    int translateLatLon_to_kilometers(struct LatLon ll);

    // test function traverse all dr_data
    void traverseAllDRData();

    private: // private functions

    long long getRecordSet_key();
    double convertLatLon_to_degree(signed long lon_or_lat);

    //=======================================
    // private variables and data
    DR_Data *genericDRData; // <----- a pointer to use with tailq
    maybe readRecordSet should return that
    //..
    // RCNM b11 + RCID b14 => name_key_identifier
    long long name_record_identifier;

    // lname AGEN + FIDN + FIDS -> lname_key_identifier
    long long lname_record_identifier;

    };

    #endif // CHARTINFO_H
    ---

    Please tell if i post to much code (or to little, i have cleaned it up
    some,
    for easier reading and removed a few lines i was trying out).

    I can Change the C file but i want to avoid that, in C declaring
    common variables
    in a header is pretty normal i think.

    So maybe what im trying to do is write a small wrapper, but i never
    done that before.


    Mic
     
    cognacc, Aug 5, 2009
    #3
  4. cognacc@

    James Kanze Guest

    On Aug 4, 9:49 pm, Victor Bazarov <> wrote:
    > cognacc@ wrote:
    > > Im trying to use some C code inside a C++ class, this class
    > > is used in another C++ class ofcourse, or will be. The C++
    > > class will contain a data structure from the C code amongst
    > > others.


    > > But in the C code header file where the datatype is defined,
    > > there are also some global variables defined.


    > That's A VERY BAD IDEA(tm). Variables should never be
    > *defined* in headers.


    Historically, the distinction between definition and declaration
    without definition is less clear in C. I think the current C
    standard says basically the same thing as the C++ standard, in
    much more round-about way---for once, the C++ standard is
    considerably clearer. But historically, a lot of C compilers
    treated file scope declarations much like a named common in
    Fortran (sort of like C++ treats the definition of a static data
    member of the instantiation of a class template). Technically,
    code which depends on this violates the C equivalent of the one
    definition rule; practically, such code exists, and (some? many?
    most?) compilers cater to it. Thus, if I have two source files,
    a.c and b.c, each with "int a;" at global (file) scope, g++ will
    complain if I compile and link them as C++, but gcc accepts the
    code.

    If I understand the orginal poster's problem, he has just such a
    C header file, and is trying to include it in a C++ program and
    compile it as C++.

    > > Is there a way to avoid multiple inclusion error, without
    > > changing the C code?


    > You could try creating another header with double inclusion
    > guards and include that C header there, but it looks like
    > you'd be better off rewriting the C stuff to make it proper.


    He'll probably end up having to rewrite a header for use in C++,
    yes. If he has access to the C code, the best solution would be
    to design the new header for dual use, and use it exclusively.
    Especially as the current header counts on something that is
    formally undefined behavior in C as well.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Aug 5, 2009
    #4
  5. * James Kanze:
    > On Aug 4, 9:49 pm, Victor Bazarov <> wrote:
    >> cognacc@ wrote:
    >>> Im trying to use some C code inside a C++ class, this class
    >>> is used in another C++ class ofcourse, or will be. The C++
    >>> class will contain a data structure from the C code amongst
    >>> others.

    >
    >>> But in the C code header file where the datatype is defined,
    >>> there are also some global variables defined.

    >
    >> That's A VERY BAD IDEA(tm). Variables should never be
    >> *defined* in headers.

    >
    > Historically, the distinction between definition and declaration
    > without definition is less clear in C. I think the current C
    > standard says basically the same thing as the C++ standard, in
    > much more round-about way---for once, the C++ standard is
    > considerably clearer. But historically, a lot of C compilers
    > treated file scope declarations much like a named common in
    > Fortran (sort of like C++ treats the definition of a static data
    > member of the instantiation of a class template). Technically,
    > code which depends on this violates the C equivalent of the one
    > definition rule; practically, such code exists, and (some? many?
    > most?) compilers cater to it. Thus, if I have two source files,
    > a.c and b.c, each with "int a;" at global (file) scope, g++ will
    > complain if I compile and link them as C++, but gcc accepts the
    > code.
    >
    > If I understand the orginal poster's problem, he has just such a
    > C header file, and is trying to include it in a C++ program and
    > compile it as C++.
    >
    >>> Is there a way to avoid multiple inclusion error, without
    >>> changing the C code?

    >
    >> You could try creating another header with double inclusion
    >> guards and include that C header there, but it looks like
    >> you'd be better off rewriting the C stuff to make it proper.

    >
    > He'll probably end up having to rewrite a header for use in C++,
    > yes. If he has access to the C code, the best solution would be
    > to design the new header for dual use, and use it exclusively.
    > Especially as the current header counts on something that is
    > formally undefined behavior in C as well.


    Not sure about that.

    As I recall, at least C99 has "tentative" filescope definitions.


    Cheers,

    - Alf
     
    Alf P. Steinbach, Aug 5, 2009
    #5
  6. cognacc@

    James Kanze Guest

    On Aug 5, 12:12 pm, Hendrik Schober <> wrote:
    > cognacc wrote:
    > > On Aug 4, 9:49 pm, Victor Bazarov <> wrote:
    > >> cognacc@ wrote:
    > >>> Im trying to use some C code inside a C++ class, this
    > >>> class is used in another C++ class ofcourse, or will be.
    > >>> The C++ class will contain a data structure from the C
    > >>> code amongst others. But in the C code header file where
    > >>> the datatype is defined, there are also some global
    > >>> variables defined.
    > >> That's A VERY BAD IDEA(tm). Variables should never be
    > >> *defined* in headers.


    > > I mean declared sorry. if in header:
    > > int Ggloabalvar; // this is a declaration right

    >
    > No, it's a definition.


    Yes, but multiple definitions are undefined behavior. A
    compiler is free to accept them. Traditionally, C compilers do,
    and C++ compilers don't; a quick experiment here showed that
    when compiling C, gcc, Sun cc/CC and VC++ all accept the
    multiple definitions without a complaint; if I compile as C++,
    only Sun CC accepts them.

    > The declaration would like this:
    > extern int Ggloabalvar;


    And
    extern int Ggloabalvar = 42 ;
    would again be a definition. The rules as to what is and is not
    a definition are not very orthogonal, having to deal with many
    historical issues, as they do.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Aug 5, 2009
    #6
  7. cognacc@

    cognacc Guest

    On Aug 5, 1:42 pm, James Kanze <> wrote:
    > On Aug 5, 12:12 pm, Hendrik Schober <> wrote:
    >
    > > cognacc wrote:
    > > > On Aug 4, 9:49 pm, Victor Bazarov <> wrote:
    > > >> cognacc@ wrote:
    > > >>> Im trying to use  some C code inside a C++ class, this
    > > >>> class is used in another C++ class ofcourse, or will be.
    > > >>> The C++ class will contain a  data structure from the C
    > > >>> code amongst others.  But in the C code header file where
    > > >>> the datatype is defined, there are also some global
    > > >>> variables defined.
    > > >> That's A VERY BAD IDEA(tm).  Variables should never be
    > > >> *defined* in headers.
    > > > I mean declared sorry. if in header:
    > > > int Ggloabalvar;  // this is a declaration right

    >
    > > No, it's a definition.

    >
    > Yes, but multiple definitions are undefined behavior.  A
    > compiler is free to accept them.  Traditionally, C compilers do,
    > and C++ compilers don't; a quick experiment here showed that
    > when compiling C, gcc, Sun cc/CC and VC++ all accept the
    > multiple definitions without a complaint; if I compile as C++,
    > only Sun CC accepts them.
    >
    > > The declaration would like this:
    > >    extern int Ggloabalvar;

    >
    > And
    >     extern int Ggloabalvar = 42 ;



    but in C if you define in global scope extern is implicit, as i
    understand K&R.
    therefore my
    int globavar; in global header.
    is the same as extern int globavar; if i understandd this correctly.
    ?

    mic
     
    cognacc, Aug 5, 2009
    #7
  8. cognacc@

    cognacc Guest

    On Aug 5, 12:12 pm, Hendrik Schober <> wrote:
    > cognacc wrote:
    > > On Aug 4, 9:49 pm, Victor Bazarov <> wrote:
    > >> cognacc@ wrote:
    > >>> Im trying to use some C code inside a C++ class, this class is used
    > >>> in another C++ class ofcourse, or will be.
    > >>> The C++ class will contain a data structure
    > >>> from the C code amongst others.
    > >>> But in the C code header file where the datatype is defined, there are
    > >>> also some global variables defined.
    > >> That's A VERY BAD IDEA(tm). Variables should never be *defined* in headers.

    >
    > > I mean declared sorry. if in header:
    > > int Ggloabalvar; // this is a declaration right

    >
    > No, it's a definition.
    > The declaration would like this:
    > extern int Ggloabalvar;
    >


    Ok then the problem is that i use these globals in multiple files i
    would then have to add
    the definiton of the variables in each file that uses these globals,
    (somewhere it said i can only
    define a variable in one place.)
    These globals are used as transfer variables. between functions,
    because the design wold be clunky
    if passing as a parameter function (because of some autogenerated
    files in the decoder. its also a prototype.

    It works flawlessky in C (where this method of sharing globals seems
    common)
    It is only when there is multiple translation units in C++ that the
    multiple definition error occurs.
    not with multiple translation units combined by C compiler

    so the decoder use some C ism not compatible with C++.

    I still want to learn if there is a way to use it without changing the
    C
    files if i i come upon some code i can't change.

    otherwise i plan to split the code into, types , transfervars, and
    defines.



    (is the extern keyword different wether its in global scope or in
    function?)
     
    cognacc, Aug 5, 2009
    #8
  9. cognacc@

    cognacc Guest

    On Aug 5, 2:33 pm, cognacc <> wrote:
    > On Aug 5, 1:42 pm, James Kanze <> wrote:


    > > Yes, but multiple definitions are undefined behavior.  A
    > > compiler is free to accept them.  Traditionally, C compilers do,
    > > and C++ compilers don't; a quick experiment here showed that
    > > when compiling C, gcc, Sun cc/CC and VC++ all accept the
    > > multiple definitions without a complaint; if I compile as C++,
    > > only Sun CC accepts them.

    >


    > but in C if you define in global scope extern is implicit, as i
    > understand K&R.
    > therefore my
    > int globavar; in global header.
    > is the same as extern int globavar; if i understandd this correctly.
    > ?

    certainly my compiler seems to disagree -:)
    Does it depends on how i include it?

    mic
     
    cognacc, Aug 5, 2009
    #9
  10. cognacc wrote:
    > On Aug 5, 2:33 pm, cognacc <> wrote:
    >> On Aug 5, 1:42 pm, James Kanze <> wrote:

    >
    >>> Yes, but multiple definitions are undefined behavior. A
    >>> compiler is free to accept them. Traditionally, C compilers do,
    >>> and C++ compilers don't; a quick experiment here showed that
    >>> when compiling C, gcc, Sun cc/CC and VC++ all accept the
    >>> multiple definitions without a complaint; if I compile as C++,
    >>> only Sun CC accepts them.

    >
    >> but in C if you define in global scope extern is implicit, as i
    >> understand K&R.
    >> therefore my
    >> int globavar; in global header.
    >> is the same as extern int globavar; if i understandd this correctly.
    >> ?

    > certainly my compiler seems to disagree -:)
    > Does it depends on how i include it?


    What exactly do you mean by "how"? Double-quotes versus angle brackets?
    I don't think it should matter.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Aug 5, 2009
    #10
  11. cognacc@

    cognacc Guest

    to James Kanze
    >If I understand the orginal poster's problem, he has just such a
    >C header file, and is trying to include it in a C++ program and
    >compile it as C++.

    exactly!

    Victor Bazarov
    > What exactly do you mean by "how"?  Double-quotes versus angle brackets?
    >   I don't think it should matter.


    Im not totally sure, im thinking about file scope like if i include
    inside a file

    1.h
    ---
    #include "global.h"
    ...
    ---

    2.h
    ---
    #include "1.h"
    ---

    2.c
    ---
    #include "2.h" or include global.h directly

    does it make a difference at.
    preprocessor level: throw everything (includes) together.
    compile level: what scope do i see from the original files
    linker level: huh!

    i tried to traceit on paper, but i can't see it yet.

    if a variabl is defined in global scope you dont have to specify
    extern
    and can use it in a function further down in the source file in a
    function, without the use of extern keyword.

    but does that also goes for the included header file at the top.
    here i say yes it does, i hope so :)

    mic
     
    cognacc, Aug 5, 2009
    #11
  12. In message
    <>,
    cognacc <> writes
    >On Aug 5, 1:42 pm, James Kanze <> wrote:
    >> On Aug 5, 12:12 pm, Hendrik Schober <> wrote:
    >>
    >> > cognacc wrote:
    >> > > On Aug 4, 9:49 pm, Victor Bazarov <> wrote:
    >> > >> cognacc@ wrote:
    >> > >>> Im trying to use  some C code inside a C++ class, this
    >> > >>> class is used in another C++ class ofcourse, or will be.
    >> > >>> The C++ class will contain a  data structure from the C
    >> > >>> code amongst others.  But in the C code header file where
    >> > >>> the datatype is defined, there are also some global
    >> > >>> variables defined.
    >> > >> That's A VERY BAD IDEA(tm).  Variables should never be
    >> > >> *defined* in headers.
    >> > > I mean declared sorry. if in header:
    >> > > int Ggloabalvar;  // this is a declaration right

    >>
    >> > No, it's a definition.

    >>
    >> Yes, but multiple definitions are undefined behavior.  A
    >> compiler is free to accept them.  Traditionally, C compilers do,
    >> and C++ compilers don't; a quick experiment here showed that
    >> when compiling C, gcc, Sun cc/CC and VC++ all accept the
    >> multiple definitions without a complaint; if I compile as C++,
    >> only Sun CC accepts them.
    >>
    >> > The declaration would like this:
    >> >    extern int Ggloabalvar;

    >>
    >> And
    >>     extern int Ggloabalvar = 42 ;

    >
    >
    >but in C if you define in global scope extern is implicit, as i
    >understand K&R.


    External *linkage* is implicit - it's accessible from other translation
    units. But the extern keyword has other effects.

    In particular, it makes what might otherwise be a definition ("this
    translation unit defines int Gglobalvar right here") into a declaration
    ("somewhere there is a translation unit which defines int Gglobalvar").


    >therefore my
    >int globavar; in global header.


    That says you're defining it right here in "this" translation unit. If
    you then include that header in more than one translation unit, you have
    multiple definitions

    >is the same as extern int globavar;


    That says it's defined in some other translation unit.


    >if i understandd this correctly.
    >?


    --
    Richard Herring
     
    Richard Herring, Aug 5, 2009
    #12
  13. cognacc wrote:
    > to James Kanze
    >> If I understand the orginal poster's problem, he has just such a
    >> C header file, and is trying to include it in a C++ program and
    >> compile it as C++.

    > exactly!
    >
    > Victor Bazarov
    >> What exactly do you mean by "how"? Double-quotes versus angle brackets?
    >> I don't think it should matter.

    >
    > Im not totally sure, im thinking about file scope like if i include
    > inside a file
    >
    > 1.h
    > ---
    > #include "global.h"
    > ..
    > ---
    >
    > 2.h
    > ---
    > #include "1.h"
    > ---
    >
    > 2.c
    > ---
    > #include "2.h" or include global.h directly


    Should not make any difference. Imagine the preprocessor like a big
    text editor that simply injects the text from the included file into the
    file that contains the 'include' directive. The resulting file (2.c')
    will have the declaration/definition, and that's what matters.

    >
    > does it make a difference at.
    > preprocessor level: throw everything (includes) together.
    > compile level: what scope do i see from the original files
    > linker level: huh!


    None. The preprocessor injects the code and walks away, the compiler
    sees your translation unit (after everything has been injected and
    macros substituted), and the linker knows the unit name, not the header
    that was included.

    >
    > i tried to traceit on paper, but i can't see it yet.
    >
    > if a variabl is defined in global scope you dont have to specify
    > extern
    > and can use it in a function further down in the source file in a
    > function, without the use of extern keyword.


    Yes. But "extern" does make a difference. 'int a;' in the global scope
    is a declaration *and* a definition, while 'extern int a;' in the global
    scope is *just* a declaration.

    > but does that also goes for the included header file at the top.
    > here i say yes it does, i hope so :)


    It does. Again, you're giving preprocessor too much credit. It's a
    rather simple code injection/rejection and macro substitution mechanism.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Aug 5, 2009
    #13
  14. cognacc@

    Jerry Coffin Guest

    In article <2033622b-d9e0-4cd8-9f41-a138d64ab3cb@
    32g2000yqj.googlegroups.com>, says...

    [ ... ]

    > Yes, but multiple definitions are undefined behavior. A
    > compiler is free to accept them. Traditionally, C compilers do,
    > and C++ compilers don't; a quick experiment here showed that
    > when compiling C, gcc, Sun cc/CC and VC++ all accept the
    > multiple definitions without a complaint; if I compile as C++,
    > only Sun CC accepts them.


    In C, _most_ instances of (what look like) multiple definitions 1)
    aren't really multiple definitions, and 2) are required to be
    accepted.

    C has a concept of a "tentative definition" that isn't present in
    C++. Specifically, a "definition" that doesn't specify a storage
    class (other than static) and doesn't include an initializer is
    really a tentative definition. So, something like:

    int x;

    // ...

    int x = 10;

    has well defined behavior -- the first is a tentative definition, and
    the second is a definition. Modulo some other reason for rejecting
    the code (e.g. exceeding an implementation limit) any properly
    functioning C compiler must accept the code and give it the
    appropriate behavior.

    The only time you get undefined behavior is if the multiple
    "definitions" disagree with each other. E.g. something like:

    static int x = 10;

    // ...

    int x;

    In this case, the first one is a real definition (not tentative) that
    defines x as having internal linkage, but the second (tentative)
    definition attempts to define x as having extern linkage (by
    default).

    Oddly enough, adding 'extern' to the second definition:

    extern int x;

    would make it _legal_, because adding extern to the definition means
    it's NOT necessarily an attempt at defining x with extern linkage! At
    the same time, IF there was no other definition of x present, the
    latter would define x as an int with extern linkage. Some parts of C
    are at least as counterintuitive as anything in C++...

    --
    Later,
    Jerry.
     
    Jerry Coffin, Aug 5, 2009
    #14
  15. On Aug 5, 2:46 pm, cognacc <> wrote:
    > On Aug 5, 12:12 pm, Hendrik Schober <> wrote:
    >
    >
    >
    > > cognacc wrote:
    > > > On Aug 4, 9:49 pm, Victor Bazarov <> wrote:
    > > >> cognacc@ wrote:
    > > >>> Im trying to use  some C code inside a C++ class, this class is used
    > > >>> in another C++ class ofcourse, or will be.
    > > >>> The C++ class will contain a  data structure
    > > >>> from the C code amongst others.
    > > >>> But in the C code header file where the datatype is defined, there are
    > > >>> also some global variables defined.
    > > >> That's A VERY BAD IDEA(tm).  Variables should never be *defined* in headers.

    >
    > > > I mean declared sorry. if in header:
    > > > int Ggloabalvar;  // this is a declaration right

    >
    > > No, it's a definition.
    > > The declaration would like this:
    > >    extern int Ggloabalvar;

    >
    > Ok then the problem is that i use these globals in multiple files i
    > would then have to add
    > the definiton of the variables in each file that uses these globals,


    No, each file that needs access to these globals must have a
    *declaration* (possibly obtained through the inclusion of a header
    file).
    Only a single source file needs to have a definition of the globals.

    > (somewhere it said i can only
    > define a variable in one place.)


    That is right. Think of it in this way:
    - A declaration tells the compiler that a variable of a certain type
    will exist somewhere in the program.
    - A definition additionally asks the compiler to set aside some space
    for that variable.
    How often do you want to reserve memory to store a particular global
    variable?

    <snip>
    > It works flawlessky in C (where this method of sharing globals seems
    > common)


    I think the (C++ compatible) method of having a declaration in a
    header and a definition in only a single source file is more common.

    --- globals.h
    extern int foo;
    extern double bar;

    --- globals.c
    #include "globals.h"

    int foo;
    double bar;

    --- EOF

    > It is only when there is multiple translation units in C++ that the
    > multiple definition error occurs.
    > not with multiple translation units combined by C compiler
    >
    > so the decoder use some C ism not compatible with C++.
    >
    > I still want to learn if there is a way to use it without changing the
    > C
    > files if i i come upon some code i can't change.


    If the unchangeable header contains definitions of global variables,
    there is no way you can use it from multiple (mixed C and) C++
    sources.

    >
    > otherwise i plan to split the code into, types , transfervars, and
    > defines.
    >
    > (is the extern keyword different wether its in global scope or in
    > function?)


    From a language viewpoint, there is no difference.
    From a programmer viewpoint, using extern outside a header is more
    error-prone, because the compiler is unable to warn you when you
    declared the variable with the wrong type.

    Bart v Ingen Schenau
     
    Bart van Ingen Schenau, Aug 6, 2009
    #15
  16. cognacc@

    cognacc Guest

    On Aug 6, 8:32 am, Bart van Ingen Schenau <>
    wrote:
    > That is right. Think of it in this way:
    > - A declaration tells the compiler that a variable of a certain type
    > will exist somewhere in the program.
    > - A definition additionally asks the compiler to set aside some space
    > for that variable.
    > How often do you want to reserve memory to store a particular global
    > variable?

    Well once but the issue is that i have different files that uses these
    globals
    where some are used as transfer variables.
    If i define it in the first included source file, then if the order of
    some operation changes
    i would need to define in the other file. plus it would clutter up
    those files.

    I tried using the global.h declarations, global.cpp definitions.
    approach.
    But then can't i only use the global var inside the global.cpp
    Its like the definitions are not seen in the global.cpp.

    also the .cpp or .h suffix doesnt matter,except for make on unix or
    other build tools, implicit rules.
    so the difference may be whether actiual source code is generated or
    not(storage ?)?.

    > If the unchangeable header contains definitions of global variables,
    > there is no way you can use it from multiple (mixed C and) C++
    > sources.

    But i can create some kind of wrapper right? so it wouldnt be included
    directly.

    Myabe since dont really need nothing but the type (definition
    declaration, ), i could overshadow the globals.
    some extern hack? or? (namemangling gets in the way ?
    or ::someglobalvarname;)
    (maybe some here says yyurggh :) )


    > > (is the extern keyword different wether its in global scope or in
    > > function?)

    >
    > From a language viewpoint, there is no difference.
    > From a programmer viewpoint, using extern outside a header is more
    > error-prone, because the compiler is unable to warn you when you
    > declared the variable with the wrong type.


    ?


    About the extern, i could *declare* as many times that i like right,
    so maybe in the start of
    the source files using it, declare extern TYPE aglobalvar; (but that
    is global scope)
    (clutter clutter :) )

    I think i found a solution with forward declaration approach, that
    seems to work (still testing), where i don't
    include the global C header directly in C++ header, (but in source cpp
    i need it).

    The drawback is i cant create any object of the type, only pointers to
    it.(i think)


    mic


    mic
     
    cognacc, Aug 6, 2009
    #16
  17. cognacc@

    James Kanze Guest

    On Aug 5, 2:33 pm, cognacc <> wrote:
    > On Aug 5, 1:42 pm, James Kanze <> wrote:
    > > On Aug 5, 12:12 pm, Hendrik Schober <> wrote:


    > > > cognacc wrote:
    > > > > On Aug 4, 9:49 pm, Victor Bazarov <> wrote:
    > > > >> cognacc@ wrote:
    > > > >>> Im trying to use some C code inside a C++ class, this
    > > > >>> class is used in another C++ class ofcourse, or will be.
    > > > >>> The C++ class will contain a data structure from the C
    > > > >>> code amongst others. But in the C code header file where
    > > > >>> the datatype is defined, there are also some global
    > > > >>> variables defined.
    > > > >> That's A VERY BAD IDEA(tm). Variables should never be
    > > > >> *defined* in headers.
    > > > > I mean declared sorry. if in header:
    > > > > int Ggloabalvar; // this is a declaration right


    > > > No, it's a definition.


    > > Yes, but multiple definitions are undefined behavior. A
    > > compiler is free to accept them. Traditionally, C compilers
    > > do, and C++ compilers don't; a quick experiment here showed
    > > that when compiling C, gcc, Sun cc/CC and VC++ all accept
    > > the multiple definitions without a complaint; if I compile
    > > as C++, only Sun CC accepts them.


    > > > The declaration would like this:
    > > > extern int Ggloabalvar;


    > > And
    > > extern int Ggloabalvar = 42 ;


    > but in C if you define in global scope extern is implicit, as
    > i understand K&R.


    Not according to the C standard. If you write:
    ing Ggloabalvar ;
    at file scope in C, it is a "tentative definition". And
    according to the C standard, "If a translation unit contains one
    or more tentative definitions for an identifier, and the
    translation unit contains no external definition for that
    identifier, then the behavior is exactly as if the translation
    unit contains a file scope declaration of that identifier, with
    the composite type as of the end of the translation unit, with
    an initializer equal to 0." In other words, if this is the only
    declaration of Ggloabalvar in the translation unit, then the
    above has exactly the same effect as if you'd written:
    int Ggloabalvar = 0 ;

    But I'm not really sure. The C standard manages to use some
    very confusing wording in this regard, and the distinction
    between a definition and a declaration isn't very clear.

    > therefore my
    > int globavar; in global header.
    > is the same as extern int globavar; if i understand this
    > correctly. ?


    I don't think so. At least, all of the compilers I have acces
    to treat them differently; without extern, "int Ggloabalvar;" is
    what C++ would call a definition, with the extern, it isn't.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Aug 6, 2009
    #17
  18. cognacc@

    James Kanze Guest

    On Aug 5, 1:39 pm, "Alf P. Steinbach" <> wrote:
    > * James Kanze:
    > > He'll probably end up having to rewrite a header for use in C++,
    > > yes. If he has access to the C code, the best solution would be
    > > to design the new header for dual use, and use it exclusively.
    > > Especially as the current header counts on something that is
    > > formally undefined behavior in C as well.


    > Not sure about that.


    > As I recall, at least C99 has "tentative" filescope definitions.


    Yes, but then end up being resolved as definitions before the
    end of the translation unit. At least as I understand it---the
    C standard is several orders of magnitude less clear than the
    C++ standard in this regard. There is one clear statement in
    §6.9: "If an identifier declared with external linkage is used
    in an expression (other than as part of the operand of a sizeof
    operator whose result is an integer constant), somewhere in the
    entire program there shall be exactly one external definition
    for the identifier; otherwise, there shall be no more than one."
    Then in §6.9.2:

    If the declaration of an identifier for an object has
    file scope and an initializer, the declaration is an
    external definition for the identifier.

    A declaration of an identifier for an object that has
    file scope without an initializer, and without a
    storage-class specifier or with the storage-class
    specifier static, constitutes a tentative definition. If
    a translation unit contains one or more tentative
    definitions for an identifier, and the translation unit
    contains no external definition for that identifier,
    then the behavior is exactly as if the translation unit
    contains a file scope declaration of that identifier,
    with the composite type as of the end of the translation
    unit, with an initializer equal to 0.

    If I understand the second paragraph correctly, it means that if
    int global ;
    is the only declaration of the variable, and it is at file
    scope, it is a tentative definition; then, since "the translation
    unit contains no external definition for that identifier", the
    behavior is as if the translation unit also contains a
    declaration:
    int global = 0 ;
    at file scope. According to the first paragraph, that would be
    an external definition, and the sentence from §6.9 says that
    there shall be no more than one such definition.

    But quite frankly, it could be a lot clearer. (Also, the only
    version of the C standard I have access to here is C99. Most C
    compilers only implement C90, though. I don't think that
    there's been a significant change in this regard, but I can't be
    sure.)

    I'm pretty sure (from memory, and you know how fallible that can
    be) that K&R 1 was ambiguous here, and that it wasn't clear
    whether the intent was to allow "int global;" in several
    different translation units or not. I'm also very sure that
    Johnson's pcc (the compiler delivered with Unix version 7 in the
    late 1980's) did allow "int global;" in as many translation
    units as desired. Or even "int global=42;", for that
    matter---if the initializers differed, it was unspecified which
    one would be used. Whether this was intentional, an artifact of
    the implementation, or maybe even a result of some
    miscommunication at Bell Labs, I don't know, and wouldn't care
    to guess.

    What is certain is that in C++, having a declaration "int
    global;" in global scope in more than one translation unit is
    undefined behavior, and that if it is also forbidden in C (which
    I believe to be the case), it is also undefined behavior, not
    requiring a diagnostic. So a compiler is perfectly free to make
    it work, and not issue a diagnostic. All of the compilers I
    have access to (gcc, Sun and VC++) do this when compiling the
    code as C. When compiling as C++, gcc (g++) and VC++ issue a
    link time error; Sun CC makes it work, with no error or warning.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Aug 6, 2009
    #18
  19. On Aug 6, 10:49 am, cognacc <> wrote:
    > On Aug 6, 8:32 am, Bart van Ingen Schenau <>
    > wrote:> That is right. Think of it in this way:
    > > - A declaration tells the compiler that a variable of a certain type
    > > will exist somewhere in the program.
    > > - A definition additionally asks the compiler to set aside some space
    > > for that variable.
    > > How often do you want to reserve memory to store a particular global
    > > variable?

    >
    > Well once but the issue is that i have different files that uses these
    > globals
    > where some are used as transfer variables.
    > If i define it in the first included source file, then if the order of
    > some operation changes
    > i would need to define in the other file. plus it would clutter up
    > those files.


    No, the file that contains the definition of a global variable does
    not affect in any way where or when the global can be used. It is up
    to the compiler (or rather, the linker) to make it work.

    >
    > I tried using the global.h declarations, global.cpp definitions.
    > approach.
    > But then can't i only use the global var inside the global.cpp
    > Its like the definitions are not seen in the global.cpp.


    You must have been doing something wrong, because I know for a fact
    that the approach works. I am using it in my current project.

    >
    > also the .cpp or .h suffix doesnt matter,except for make on unix or
    > other build tools, implicit rules.
    > so the difference may be whether actiual source code is generated or
    > not(storage ?)?.


    The suffix may not matter for the compiler (although most will have
    some recognition mechanism to automatically detect source files in
    different languages), the suffixes are very important for the human
    developers to keep the different kinds of files apart.

    Header files (common suffixes: .h, .hpp, .hxx) are meant for inclusion
    in multiple other headers or source files. This means that care must
    be taken when writing these files that including them multiple times
    (both in a single TU(*) as in multiple TUs) does not lead to problems.

    Source files (common suffixes: .c, .cpp, .C, .cxx) are meant to be
    compiled directly and will typically contain definitions that may not
    be repeated within a program.

    (*): A TU is what you get after including all referenced headers in a
    source file. This is what the compiler actually translates into an
    object file.

    >
    > > If the unchangeable header contains definitions of global variables,
    > > there is no way you can use it from multiple (mixed C and) C++
    > > sources.

    >
    > But i can create some kind of wrapper right? so it wouldnt be included
    > directly.


    No, creating a wrapper will not help you here.

    >
    > Myabe since dont really need nothing but the type (definition
    > declaration, ), i could overshadow the globals.
    > some extern hack? or? (namemangling gets in the way ?
    > or ::someglobalvarname;)
    > (maybe some here says yyurggh :) )
    >
    > > > (is the extern keyword different wether its in global scope or in
    > > > function?)

    >
    > > From a language viewpoint, there is no difference.
    > > From a programmer viewpoint, using extern outside a header is more
    > > error-prone, because the compiler is unable to warn you when you
    > > declared the variable with the wrong type.

    >
    > ?
    >
    > About the extern, i could *declare* as many times that i like right,
    > so maybe in the start of
    > the source files using it, declare extern TYPE aglobalvar; (but that
    > is global scope)
    > (clutter clutter :) )


    That is possible, but has the problem that you may get the TYPE wrong,
    without any warning from the compiler.

    >
    > mic


    Bart v Ingen Schenau
     
    Bart van Ingen Schenau, Aug 6, 2009
    #19
  20. cognacc@

    cognacc Guest

    On Aug 6, 1:06 pm, Bart van Ingen Schenau <>
    wrote:
    > > Well once but the issue is that i have different files that uses these
    > > globals
    > > where some are used as transfer variables.
    > > If i define it in the first included source file, then if the order of
    > > some operation changes
    > > i would need to define in the other file. plus it would clutter up
    > > those files.

    >
    > No, the file that contains the definition of a global variable does
    > not affect in any way where or when the global can be used. It is up
    > to the compiler (or rather, the linker) to make it work.

    Well i would have to add sometinhg to my source files, i would not be
    able to do it
    without defining the variable (if the global header declared variables
    using extern)


    > > I tried using the global.h declarations, global.cpp definitions.
    > > approach.
    > > But then can't i only use the global var inside the global.cpp
    > > Its like the definitions are not seen in the global.cpp.


    I meant using them outside the global.cpp, (see next pragraph)

    > You must have been doing something wrong, because I know for a fact
    > that the approach works. I am using it in my current project.


    I think i might have forgot to add it in my make file (oops), but im
    not sure.

    > > also the .cpp or .h suffix doesnt matter,except for make on unix or
    > > other build tools, implicit rules.
    > > so the difference may be whether actiual source code is generated or
    > > not(storage ?)?.

    >
    > The suffix may not matter for the compiler (although most will have
    > some recognition mechanism to automatically detect source files in
    > different languages), the suffixes are very important for the human
    > developers to keep the different kinds of files apart.

    I was thinking in terms of what you would put inside a header file and
    what you would
    put in source file.
    I have been taught that common variables (globals) in C, and also some
    other guidelines.
    but never thought of it in terms of code generation, storage
    requirements.
    But this would trip me up when using in it C++.


    > Header files (common suffixes: .h, .hpp, .hxx) are meant for inclusion
    > in multiple other headers or source files. This means that care must
    > be taken when writing these files that including them multiple times
    > (both in a single TU(*) as in multiple TUs) does not lead to problems.
    >
    > Source files (common suffixes: .c, .cpp, .C, .cxx) are meant to be
    > compiled directly and will typically contain definitions that may not
    > be repeated within a program.
    >
    > (*): A TU is what you get after including all referenced headers in a
    > source file. This is what the compiler actually translates into an
    > object file.


    Thanks i tried finding somewhere where exactly what a translation unit
    was described.
    look in the gcc manual but couldnt find it.
    Is there some authorative place to look it up. (the standard? - i dont
    have those!)


    >
    > > > From a language viewpoint, there is no difference.
    > > > From a programmer viewpoint, using extern outside a header is more
    > > > error-prone, because the compiler is unable to warn you when you
    > > > declared the variable with the wrong type.



    > Bart v Ingen Schenau


    Thanks Bart you managed to confuse me :),
    because it seems a bit at odds with what others are saying.
    Are you seeing it from a C perspective or something.
    Or maybe i just dont understand it yet. Have to think!

    I would want to be more precise, but i have to go now, sorry.
    I expand later if neccesarry.


    mic
     
    cognacc, Aug 8, 2009
    #20
    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. Andy Eshtry
    Replies:
    0
    Views:
    647
    Andy Eshtry
    Mar 1, 2004
  2. keithb
    Replies:
    1
    Views:
    962
    Bruce Barker
    Mar 29, 2006
  3. E11
    Replies:
    1
    Views:
    4,953
    Thomas Weidenfeller
    Oct 12, 2005
  4. =?ISO-8859-2?Q?Miros=B3aw?= Makowiecki

    Decralation of class inside other class and definition outside this class

    =?ISO-8859-2?Q?Miros=B3aw?= Makowiecki, Jul 13, 2007, in forum: C++
    Replies:
    2
    Views:
    359
    Alf P. Steinbach
    Jul 13, 2007
  5. Casey Hawthorne
    Replies:
    1
    Views:
    759
    Arne Vajhøj
    Mar 18, 2009
Loading...

Share This Page