Operator overloading in C

Discussion in 'C Programming' started by jacob navia, Aug 8, 2003.

  1. jacob navia

    jacob navia Guest

    C++ introduced an interesting feature (among others): operator overloading.

    The idea is to build a mechanism for the user defining its own number types and the operations to be
    done with them.

    I decided to build it in the lcc-win32 distribution, and this feature allowed me to introduce 350
    bit floats.

    Yes, 350. We have a lot of fast machines now. Why not use them? The extra-precision is useful in
    some algorithms.

    This extension to C is transparent, since it doesn't change anything in the basics of the language.
    The syntax used is:

    TYPE operator+(TYPE a,TYPE b)
    {
    }

    When in your program you use
    TYPE a,b;
    ...
    a+b;
    Means that you call the operator function with those two numbers. This is similar to C++, but since
    there are no classes (C is not object oriented) everything is quite simple.

    Note that this is an extension compatible with C and it is important to know that the C standard
    doesn't forbid extensions. They should not introduce new keywords though.

    In my implementation it means that

    int operator = 6;

    still works as it should. No new keywords.

    The operator symbol is recognized if (and only if):
    1) The level is global, i.e. not within a function definition.
    2) It is followed by one of the defined operator symbols (+, -, etc)
    3) This must be followed by a normal function definition. The name of this function is the sequence
    of types in the argument list, the "signature" in technical terms.

    Is this useful?

    Yes, for numbers it is ideal. It is less so, when the data types aren't quantities but other
    relationships or data. Take, for instance
    String a,b,c;
    ...
    c = a+b;

    This means that a+b is different from b+a. Not very clear.

    Operator overloding *can* be useful, specially for letting the users build new kinds of numbers,
    that fulfill special needs.

    What do you think?

    Voice your opinion. In any case Lcc-win32 is available at:

    http://www.cs.virginia.edu/~lcc-win32
    jacob navia, Aug 8, 2003
    #1
    1. Advertising

  2. jacob navia

    bd Guest

    On Fri, 08 Aug 2003 21:53:32 +0200, jacob navia wrote:

    > C++ introduced an interesting feature (among others): operator overloading.
    >
    > The idea is to build a mechanism for the user defining its own number types and the operations to be
    > done with them.
    >
    > I decided to build it in the lcc-win32 distribution, and this feature allowed me to introduce 350
    > bit floats.


    [snip]

    This is offtopic for comp.lang.c. comp.std.c is for discussion of changes
    to the standard.

    --
    Freenet distribution not available
    "Let's show this prehistoric bitch how we do things downtown!"
    -- The Ghostbusters
    bd, Aug 8, 2003
    #2
    1. Advertising

  3. jacob navia

    Martijn Guest

    bd wrote:
    >> I decided to build it in the lcc-win32 distribution, and this
    >> feature allowed me to introduce 350 bit floats.

    >
    > [snip]
    >
    > This is offtopic for comp.lang.c. comp.std.c is for discussion of
    > changes
    > to the standard.


    How do you gather that he is trying to change the standard? He is merely
    suggesting an extension. I quote: "and it is important to know that the C
    standard doesn't forbid extensions".

    I guess is more of a moral one (which may or may not be off topic).

    In regards to the original question: I wouldn't use it because I prefer to
    stick to the standard, but I find the concept very neat and I do think it
    would be a useful extension which could clarify and simplify code.

    Good luck,

    --
    Martijn Haak
    http://www.sereneconcepts.nl
    Martijn, Aug 8, 2003
    #3
  4. jacob navia

    jacob navia Guest

    "David Rubin" <> wrote in message news:...
    > jacob navia wrote:
    >
    > [snip - I introduced operator overloading as an extension to my compiler
    > suite]
    > > What do you think?

    >
    > If you want to use C++ features, use C++.
    >
    > /david


    Obviously I do not agree with that. C++ is a very complex language, and is missing an essential
    facility I found only in C: I like to build my structures/data as I want, without any object
    oriented framework imposed by the language.

    There are many things innovative in C++, but not all of it. This idea solves a problem that can't be
    solved in C easily, without adding any C++ complexity.

    jacob
    jacob navia, Aug 9, 2003
    #4
  5. jacob navia

    jacob navia Guest

    "bd" <-ip.org> wrote in message
    news:p-ip.org...
    > On Fri, 08 Aug 2003 21:53:32 +0200, jacob navia wrote:
    >
    > > C++ introduced an interesting feature (among others): operator overloading.
    > >
    > > The idea is to build a mechanism for the user defining its own number types and the operations

    to be
    > > done with them.
    > >
    > > I decided to build it in the lcc-win32 distribution, and this feature allowed me to introduce

    350
    > > bit floats.

    >
    > [snip]
    >
    > This is offtopic for comp.lang.c. comp.std.c is for discussion of changes
    > to the standard.
    >


    I wouldn't say the standard should be changed, at least not before a good discussion. This is what
    comp.lang.c is all about isn't it?

    Discussion about C.

    Operator overloading allows the easy introduction of new numeric types without much problems. I am
    not saying is "the solution" for all problems but is "a solution" for the introduction of
    1) Higher precision numbers
    2) Bignums (arbitrary precision numbers)
    3) Rationals (Numbers expressed as integer ratios 5/9, for instance)
    4) Quaternions

    and many others. To do this in C requires
    divide(add(a,b),sub(a,b))
    instead of
    (a+b)/(a-b)

    jacob
    jacob navia, Aug 9, 2003
    #5
  6. jacob navia

    Malcolm Guest

    "jacob navia" <> wrote in message
    >
    > Operator overloading allows the easy introduction of new numeric
    > types without much problems
    >

    I wrote a big number package in C++. It had plenty of problems, for instance
    I added a user defined cast to long to try to simplify the code, and
    promptly broke everything I had written previously.
    Malcolm, Aug 9, 2003
    #6
  7. "jacob navia" <> writes:

    > C++ introduced an interesting feature (among others): operator
    > overloading.


    <explanation snipped>

    Just my 2c: operator (and function) overloading are about the only C++
    features I miss since I switched (back) to C.

    I think a number of replies to your post reflect the fear that, as
    soon as one starts to introduce new features, it will be impossible to
    stop and C will soon become as complex as C++. And I don't deny that
    there may be some truth in this claim.

    Good luck,

    --
    Stefano
    Stefano Ghirlanda, Aug 9, 2003
    #7
  8. jacob navia

    jacob navia Guest

    "Malcolm" <> wrote in message news:bh2kjr$2fd$...
    >
    > "jacob navia" <> wrote in message
    > >
    > > Operator overloading allows the easy introduction of new numeric
    > > types without much problems
    > >

    > I wrote a big number package in C++. It had plenty of problems, for instance
    > I added a user defined cast to long to try to simplify the code, and
    > promptly broke everything I had written previously.


    Well, give lcc-win32 a try. I will be glad to help you if you find problems with it.
    jacob
    jacob navia, Aug 9, 2003
    #8
  9. jacob navia

    jacob navia Guest

    "Zeljko Vrba" <> wrote in message news:...
    > In article <bh0vl6$nfk$>, jacob navia wrote:
    > >
    > > What do you think?
    > >

    > I wouldn't use it because of:
    > - it is supported only by your compiler; if I want to make my program available
    > to general public (i.e. UNIX systems, non x86 systems), the feature is useless
    > - I don't find prefix, function-call synax hard, and it's standard C
    > - unclear semantics: given
    >
    > BIGNUM operator+(BIGNUM, double)
    >
    > and an expression like a+2 (where a is BIGNUM), will 2 get converted to
    > double or an error will result?
    >

    If you compile this
    #include <stdio.h>
    typedef struct tagB {
    int a;
    int b;
    } B;

    B operator+(B a,double d)
    {
    printf("operator + called\n");
    return a;
    }

    int main(void)
    {
    B a,b;

    a = a+2;
    return 0;
    }
    This produces
    "operator + called"

    > Will this allow me to define additional
    > BIGNUM operator+(BIGNUM, int)
    >

    Yes. But in that case the int operator+ will be called. The algorithm first seeks a correct match
    without any promotions. Then it will do "the usual conversions", then it will look if there are
    defined casts that could match.
    > I say C++ features are best left to C++.


    I say operator overloading is useful.
    jacob navia, Aug 9, 2003
    #9
  10. jacob navia

    Zeljko Vrba Guest

    In article <bh2ohn$a1e$>, jacob navia wrote:
    >
    > I say operator overloading is useful.
    >

    I didn't say it isn't. But then use C++. Nobody forces you to use classes,
    inheritance, access levels and other C++ novelties. You can use it just as
    an "enhanced C" using only features that you like/need/feel comfortable with.

    Don't get me wrong: you did a tremendous amount of work coding a C compiler
    and I admire that (having listened through 2 semesters of formal languages
    and automata theory at faculty I know what is involved :)).

    I just don't feel comfortable about spreading around another variant of C
    with its own extensions that are incompatible with others in a fundamental
    way (code written for your compiler would need a major revision if/when need
    arises to port it to ANSI C).

    Diversity of dialects killed LISP (the only other language I find beautiful
    besides C) and Basic (at least until Gates "standardized" it). We shouldn't
    be doing it to C too.
    Zeljko Vrba, Aug 9, 2003
    #10
  11. jacob navia

    jacob navia Guest

    "Stefano Ghirlanda" <> wrote in message
    news:...
    > "jacob navia" <> writes:
    >
    > > C++ introduced an interesting feature (among others): operator
    > > overloading.

    >
    > <explanation snipped>
    >
    > Just my 2c: operator (and function) overloading are about the only C++
    > features I miss since I switched (back) to C.
    >
    > I think a number of replies to your post reflect the fear that, as
    > soon as one starts to introduce new features, it will be impossible to
    > stop and C will soon become as complex as C++. And I don't deny that
    > there may be some truth in this claim.
    >


    Yes, and the experience of C++ should be a warning to all that start the same way:

    KNOW WHEN TO STOP.

    jacob
    jacob navia, Aug 9, 2003
    #11
  12. jacob navia

    Serve La Guest

    "Zeljko Vrba" <> wrote in message
    news:...
    > In article <bh2ohn$a1e$>, jacob navia wrote:
    > >
    > > I say operator overloading is useful.
    > >

    > I didn't say it isn't. But then use C++. Nobody forces you to use classes,
    > inheritance, access levels and other C++ novelties. You can use it just as
    > an "enhanced C" using only features that you like/need/feel comfortable

    with.

    wrong. If you work with people that use C++, you can be sure that at some
    point you have to use class, inheritance, access levels and other C++
    novelties. This is only true if you work alone.
    Serve La, Aug 10, 2003
    #12
  13. jacob navia

    Andre Guest

    Serve La wrote:
    > "Zeljko Vrba" <> wrote in message
    > news:...
    >
    >>In article <bh2ohn$a1e$>, jacob navia wrote:
    >>
    >>>I say operator overloading is useful.
    >>>

    >>
    >>I didn't say it isn't. But then use C++. Nobody forces you to use classes,
    >>inheritance, access levels and other C++ novelties. You can use it just as
    >>an "enhanced C" using only features that you like/need/feel comfortable

    >
    > with.
    >
    > wrong. If you work with people that use C++, you can be sure that at some
    > point you have to use class, inheritance, access levels and other C++
    > novelties. This is only true if you work alone.


    Exactly. If you're into component development and enjoy abstraction and
    reusability, there's always going to be class, inheritance etc involved.
    Also, what Zeljko said is also only true when you deliberately force an
    application, that could benifit from Object orientation, to comply in a
    non-OO fashion. Like Serve said, if you're working alone, you're the boss.

    -Andre
    Andre, Aug 10, 2003
    #13
  14. jacob navia

    Dan Pop Guest

    In <bh0vl6$nfk$> "jacob navia" <> writes:

    >The syntax used is:
    >
    >TYPE operator+(TYPE a,TYPE b)
    >{
    >}
    >
    >When in your program you use
    > TYPE a,b;
    > ...
    > a+b;
    >Means that you call the operator function with those two numbers. This is similar to C++, but since
    >there are no classes (C is not object oriented) everything is quite simple.
    >
    >Note that this is an extension compatible with C and it is important to know that the C standard
    >doesn't forbid extensions. They should not introduce new keywords though.


    The C standard requires a diagnostic for

    TYPE operator+(TYPE a,TYPE b) {}

    because it is syntactically invalid in C. The only extensions allowed
    by the C standard are those based on undefined behaviour. So, to make
    your extension compatible with standard C, replace "operator" by a an
    identifier in the implementation name space, e.g. __operator__:

    TYPE __operator__+(TYPE a,TYPE b) {}

    invokes undefined behaviour (a reserved identifier not explicitly defined
    by the C standard is used), therefore no diagnostic is needed, and your
    compiler is free to silently overload the + operator as a result.

    This technique of adding extensions is widely used by GNU C, so that
    people can still use them if they invoke gcc in standard C mode. If your
    compiler has also a non-standard C mode, you can use both "operator" and
    "__operator__" in that mode. When invoked in standard C mode, "operator"
    becomes an indentifier in the program namespace, though.

    >In my implementation it means that
    >
    >int operator = 6;
    >
    >still works as it should. No new keywords.


    It doesn't matter, TYPE operator+(TYPE a,TYPE b) {} still requires a
    diagnostic, according to the C syntax.

    >The operator symbol is recognized if (and only if):
    >1) The level is global, i.e. not within a function definition.
    >2) It is followed by one of the defined operator symbols (+, -, etc)
    >3) This must be followed by a normal function definition. The name of this function is the sequence
    >of types in the argument list, the "signature" in technical terms.


    That's wrong, again. Such names are in the program name space, you can't
    define them by magic. Use the __ prefix to fix the issue. But you have
    an additional problem: if the function signature is the function name,
    how do you distiguish between operators with identical signatures, e.g.

    TYPE operator+(TYPE a,TYPE b) {...}
    TYPE operator-(TYPE a,TYPE b) {...}

    >Is this useful?


    The answer is mostly an issue of religion. For better acceptance, don't
    allow TYPE to be any of the C scalar types.

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
    Dan Pop, Aug 11, 2003
    #14
  15. jacob navia

    jacob navia Guest

    "Dan Pop" <> wrote in message news:bh88o1$qpj$...
    > In <bh0vl6$nfk$> "jacob navia" <> writes:
    >

    [snip]
    > But you have
    > an additional problem: if the function signature is the function name,
    > how do you distiguish between operators with identical signatures, e.g.
    >
    > TYPE operator+(TYPE a,TYPE b) {...}
    > TYPE operator-(TYPE a,TYPE b) {...}
    >


    The name of the first operator is:

    _operator_plus_TYPE_TYPE
    the second is
    _operator_minus_TYPE_TYPE


    The biggest problem I had is the pointer problem.
    The operator + can't be defined with types like

    TYPE operator+(TYPE a,int b)

    since the operation a+7

    is used in the language already (means a + 7 *sizeof(a)) and would
    clash with standard C. This restriction is applied to all operators.

    In any way, the compiler has several flags that make it reject any
    non-standard grammar like this (-ansic) or even go back to ansi 89.

    jacob
    jacob navia, Aug 11, 2003
    #15
  16. jacob navia

    Jun Woong Guest

    "Dan Pop" <> wrote in message news:bhasgl$dpg$...
    > In <bh8h8c$ddb$> "jacob navia" <> writes:
    >
    >
    > >"Dan Pop" <> wrote in message news:bh88o1$qpj$...
    > >> In <bh0vl6$nfk$> "jacob navia" <> writes:
    > >>

    > >[snip]
    > >> But you have
    > >> an additional problem: if the function signature is the function name,
    > >> how do you distiguish between operators with identical signatures, e.g.
    > >>
    > >> TYPE operator+(TYPE a,TYPE b) {...}
    > >> TYPE operator-(TYPE a,TYPE b) {...}
    > >>

    > >
    > >The name of the first operator is:
    > >
    > >_operator_plus_TYPE_TYPE
    > >the second is
    > >_operator_minus_TYPE_TYPE

    >
    > That's not good enough, you really need *two* preceding underscores.


    One can think they are good enough. Those function names doesn't
    pollute the users' valid name space.


    --
    Jun, Woong ()
    Dept. of Physics, Univ. of Seoul
    Jun Woong, Aug 12, 2003
    #16
  17. jacob navia

    Richard Bos Guest

    "Jun Woong" <> wrote:

    > "Dan Pop" <> wrote in message news:bhasgl$dpg$...
    > > In <bh8h8c$ddb$> "jacob navia" <> writes:
    > >
    > > >The name of the first operator is:
    > > >
    > > >_operator_plus_TYPE_TYPE
    > > >the second is
    > > >_operator_minus_TYPE_TYPE

    > >
    > > That's not good enough, you really need *two* preceding underscores.

    >
    > One can think they are good enough. Those function names doesn't
    > pollute the users' valid name space.


    Not on a file scope level, but they can be blocked within a block scope,
    and then you're in trouble - you try debugging why just this operator
    won't work for just these types in just this function, and no others.
    You could, of course, reserve these names for yourself, but it's better
    to make sure.

    Richard
    Richard Bos, Aug 12, 2003
    #17
  18. jacob navia

    Jun Woong Guest

    "Richard Bos" <> wrote in message news:...
    > "Jun Woong" <> wrote:
    >
    > > "Dan Pop" <> wrote in message news:bhasgl$dpg$...
    > > > In <bh8h8c$ddb$> "jacob navia" <> writes:
    > > >
    > > > >The name of the first operator is:
    > > > >
    > > > >_operator_plus_TYPE_TYPE
    > > > >the second is
    > > > >_operator_minus_TYPE_TYPE
    > > >
    > > > That's not good enough, you really need *two* preceding underscores.

    > >
    > > One can think they are good enough. Those function names doesn't
    > > pollute the users' valid name space.

    >
    > Not on a file scope level, but they can be blocked within a block scope,


    Oh, I missed that those names can be inserted where the overloaded
    operators are actually used in an expression.

    Thanks.


    --
    Jun, Woong ()
    Dept. of Physics, Univ. of Seoul
    Jun Woong, Aug 12, 2003
    #18
  19. jacob navia

    jacob navia Guest

    "Dan Pop" <> wrote in message news:bhasgl$dpg$...
    > In <bh8h8c$ddb$> "jacob navia" <> writes:
    >
    > >> TYPE operator+(TYPE a,TYPE b) {...}
    > >> TYPE operator-(TYPE a,TYPE b) {...}
    > >>

    > >
    > >The name of the first operator is:
    > >
    > >_operator_plus_TYPE_TYPE
    > >the second is
    > >_operator_minus_TYPE_TYPE

    >
    > That's not good enough, you really need *two* preceding underscores.
    >


    Of course, the compiler adds another underscore, as with any other function. The
    resulting name in the object file (that can be dumped) is:

    __operator_minus_TYPE_TYPE

    > As I already said, operator overloading should not be implemented for
    > scalar types.


    This would be an enormous restriction Dan.

    I see the usage of this mainly for defining new types of NUMBERS.
    Then, it is paramount to have conversion features, and interaction with
    native types. For instance when using the qfloat data type (350 bits
    precision) you can write:

    qfloat b = 67;
    qfloat c = b+1;

    This is because there is an operator defined like this:

    qfloat operator+(qfloat,int);

    In standard C it is not possible to add an integer to a structure, so
    I STAY within UB (undefined behavior) and my implementation
    can't clash with the C standard.

    Am I correct?
    Can you explain your motivations why this is incorrect?

    Thanks

    jacob
    jacob navia, Aug 12, 2003
    #19
  20. jacob navia

    jacob navia Guest


    > I believe Dan is referring to int operator+(int, int); and similar - any
    > operation that is already defined by the C standard.


    Of course. One of the arguments *must* be a user defined type.

    There are two kinds operators:
    monadic (! for instance) and dyadic (+, -, etc)
    At least one argument must be a user defined type, and there is a table
    in the documentation indicating where pointers are possible. For instance
    pointer multiplication or division is undefined in C, so you can safely
    define operators to those functions that take pointers.

    Addition and above all subtraction can't take plain pointers.

    A simplification is done with the cast operator

    typea operator()(typeb a) { }

    This means that when you write:
    typeb b;
    typea a;

    a = (typea)b;

    the above conversion function is called.

    If you do not add this, the code becomes messy, with too many ad hoc
    operators that define the same thing.

    A big problem with my schema is type aliasing.

    When you write:
    typedef unsigned long DWORD;

    and later:
    type operator+(type,DWORD);

    should the operator accept unsigned ints?
    Or only DWORDS?

    Questions and questions. One of the reasons of this discussion is
    to hear to opinion of other people more clever than me.

    What do you think?

    jacob

    P.S. concerning your other remark:
    > It's not the name in the object file, it's the name in the C namespace
    > that matters. _operator_minus_TYPE_TYPE is a valid name for a user
    > program to use for a block-scope identifier.


    I thought that identifiers beginning with _ are reserved and should not be used.
    Should I add a new underscore? (Not very difficult to do).


    "Kevin Easton" <> wrote in message
    news:newscache$2g5jjh$urc$...
    > jacob navia <> wrote:
    > >
    > > "Dan Pop" <> wrote in message news:bhasgl$dpg$...
    > >> In <bh8h8c$ddb$> "jacob navia" <> writes:
    > >>
    > >> >> TYPE operator+(TYPE a,TYPE b) {...}
    > >> >> TYPE operator-(TYPE a,TYPE b) {...}
    > >> >>
    > >> >
    > >> >The name of the first operator is:
    > >> >
    > >> >_operator_plus_TYPE_TYPE
    > >> >the second is
    > >> >_operator_minus_TYPE_TYPE
    > >>
    > >> That's not good enough, you really need *two* preceding underscores.
    > >>

    > >
    > > Of course, the compiler adds another underscore, as with any other function. The
    > > resulting name in the object file (that can be dumped) is:
    > >
    > > __operator_minus_TYPE_TYPE

    >
    > It's not the name in the object file, it's the name in the C namespace
    > that matters. _operator_minus_TYPE_TYPE is a valid name for a user
    > program to use for a block-scope identifier.
    >
    > >> As I already said, operator overloading should not be implemented for
    > >> scalar types.

    > >
    > > This would be an enormous restriction Dan.
    > >
    > > I see the usage of this mainly for defining new types of NUMBERS.
    > > Then, it is paramount to have conversion features, and interaction with
    > > native types. For instance when using the qfloat data type (350 bits
    > > precision) you can write:
    > >
    > > qfloat b = 67;
    > > qfloat c = b+1;
    > >
    > > This is because there is an operator defined like this:
    > >
    > > qfloat operator+(qfloat,int);
    > >
    > > In standard C it is not possible to add an integer to a structure, so
    > > I STAY within UB (undefined behavior) and my implementation
    > > can't clash with the C standard.
    > >
    > > Am I correct?
    > > Can you explain your motivations why this is incorrect?

    >
    > I believe Dan is referring to int operator+(int, int); and similar - any
    > operation that is already defined by the C standard.
    >
    > - Kevin.
    >
    jacob navia, Aug 13, 2003
    #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. John Smith
    Replies:
    2
    Views:
    415
    Ivan Vecerina
    Oct 6, 2004
  2. Replies:
    11
    Views:
    722
    James Kanze
    May 16, 2007
  3. hurcan solter
    Replies:
    3
    Views:
    717
    Cholo Lennon
    Aug 29, 2007
  4. Replies:
    11
    Views:
    547
  5. Replies:
    2
    Views:
    303
Loading...

Share This Page