Page 2 of 2 First 12
  • Jump to page:
    #16
  1. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,073
    Rep Power
    1802
    It is normally considered bad practice to pass function calls, or expressions as parameters in C. This is a perfect example of why this is so.

    Most professional coding standards are defined, not to restrict the programmers creative talent, but to prevent the unwary from getting into exactly this sort of problem - to avoid undefined behaviour.

    Simply evaluate expressions and functions to temporary variables, and pass the variables. That avoids the problem, and is easier to debug.

    Clifford
  2. #17
  3. No Profile Picture
    status unknown
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Posts
    262
    Rep Power
    11
    If it's considered bad practice, almost every programmer I've ever met is guilty. Using a function call as a parameter is fine. Making assumptions about the order of evaluation is not. Of course, if a compiler documents that it will always evaluate function arguments in a particular order then it can be relied upon, but it's not portable - perhaps not even to the next version of the same compiler.

    By the way it's unspecified behaviour rather than undefined behaviour.
  4. #18
  5. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95
    bigbadbob i think you would make a very good contractual lawyer ;)
  6. #19
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,088
    Rep Power
    2222
    I couldn't get to test the program until this morning. And then it took all day before I could get online.

    First I tried it with MinGW gcc in the DOS window and I got the same reversed order.

    Then I tried it with Visual C++ 1.52. I chose this version over v6 because the __pascal keyword needed in the next test is no longer supported.

    Here's the code, followed by the output. The source code file serves as the test file, so we would expect the first three characters to be "#in":
    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    
    void __pascal doit(int c1, int c2, int c3);
    
    int main(void)
    {
        int  i;
        FILE *fp;
    
        if ((fp = fopen("fgetc.c","rt")) == NULL)
        {
            perror("file open");
            exit(1);
        }
    
        printf("From Main: %c %c %c\n", fgetc(fp), fgetc(fp), fgetc(fp)); 
        fclose(fp);
    
        if ((fp = fopen("fgetc.c","rt")) == NULL)
        {
            perror("file open");
            exit(1);
        }
    
        doit(fgetc(fp), fgetc(fp), fgetc(fp)); 
        fclose(fp);
    
        if ((fp = fopen("fgetc.c","rt")) == NULL)
        {
            perror("file open");
            exit(1);
        }
    
        printf("A safe way:"); 
        for (i=0; i<3; i++)
            printf(" %c", fgetc(fp)); 
        printf("\n"); 
        fclose(fp);
    
        return 0;
    }
    
    void __pascal doit(int c1, int c2, int c3)
    {
        printf("From pascal function: %c %c %c\n", c1,c2,c3);
    }
    Output:
    C:\dcw\PROJECTS\TEST\argorg>argorg
    From Main: n i #
    From pascal function: # i n
    A safe way: # i n

    C:\dcw\PROJECTS\TEST\argorg>
    So the compiler does not protect us against side-effects, resulting in the function calling convention dictating the order in which the characters are displayed. A safer way would be to either output each character before the next one is read (as in my "safe way" example) or to save them into a buffer in the order read for output later.
  8. #20
  9. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,073
    Rep Power
    1802
    Originally posted by BigBadBob
    If it's considered bad practice, almost every programmer I've ever met is guilty. Using a function call as a parameter is fine. Making assumptions about the order of evaluation is not. Of course, if a compiler documents that it will always evaluate function arguments in a particular order then it can be relied upon, but it's not portable - perhaps not even to the next version of the same compiler.

    By the way it's unspecified behaviour rather than undefined behaviour.
    I work as professional developer, heading teams of developers. Less experienced deveopers cost less money. In order to ensure code quality, a coding standard is imposed. The coding standard is intended to promote safe and robust coding practices that remain so through several years of code maintenance, re-use, and porting. This is a commercial consideration, in the long term it saves money.

    In such a commercial environment, utilising knowledge of compiler dependent behaviour is normally unwise. That said, I once wrote code that assumed that a right-shift of a signed int did sign extension (for performance reasons - it was an interrupt routine). So sometimes certain practices can be justified, however I see no justification for the code posted in the original message.

    Clifford
  10. #21
  11. No Profile Picture
    status unknown
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Posts
    262
    Rep Power
    11
    Originally posted by clifford
    I work as professional developer, heading teams of developers. Less experienced deveopers cost less money. In order to ensure code quality, a coding standard is imposed. The coding standard is intended to promote safe and robust coding practices that remain so through several years of code maintenance, re-use, and porting. This is a commercial consideration, in the long term it saves money.
    Coding standards are a good thing. A couple of years ago I was working for a very large company with many divisions spread across multiple sites. I was in responsible for a number of development teams and it became obvious that each team was working to a different C coding standard and all of them produced elsewhere. I tasked one of my senior developers with producing an in-house version. He did a reasonable job. A few months later someone from of the other divisions noticed the new standard on the company intranet and mentioned it in one of the company newsgroups. There followed much debate about the pros and cons of various items in the coding standard, with a great deal of religious heat generated.

    The point I'm making is that there's no absolute consensus on what should or shouldn't be in a coding standard. Another name for a coding standard is a style guide, and therein lies a clue to the problem, it's about style. And it's almost impossible to get a large number of talented programmers to agree on style.

    If it works for you and your teams in your environment to avoid using function calls as parameters then that's great. But some other places might consider that an unnecessary constraint (and others might agree with you). Each to their own. I'm not knocking coding standards, nor your own coding standard, but a consensus is difficult to achieve.

    In such a commercial environment, utilising knowledge of compiler dependent behaviour is normally unwise. That said, I once wrote code that assumed that a right-shift of a signed int did sign extension (for performance reasons - it was an interrupt routine). So sometimes certain practices can be justified, however I see no justification for the code posted in the original message.
    [/B]
    I agree with you. That said, the code posted is standard conforming. But it's not portable.
  12. #22
  13. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,073
    Rep Power
    1802
    Originally posted by BigBadBob
    Another name for a coding standard is a style guide, and therein lies a clue to the problem, it's about style. And it's almost impossible to get a large number of talented programmers to agree on style.
    That is a common misconception, a distinction must be made; a style guide is not a coding standard (although it may form part of one, but in my opinion they are better kept separate). While a style guide is intended to aid readability and clarity by imposing consistency, a coding standard legislates what parts of a language may be used, and how. The aim of a coding standard, by this definition, is to avoid language behaviour that either may differ between compilers, is ill defined by the standard (or undefined), or is commonly misused or misunderstood by practitioners (this case falls into the first and last category).

    I agree that style guides cause religious argument, and are often unhelpful. The guide I produced is flexible, comprises mainly of recommendations rather than absolute directives, legislating against only those practices that are particularly perverse (such as over decorated comment blocks). In most cases, a directive is backed up by justification, and where possible I give acceptable alternatives. The reference for much of this work was Code Complete by Steve McConnell (Microsoft Press), and while even I disagree with some of his ideas, it is well worth looking at (and is superbly written).

    A coding standard on the other hand is a more technical document, and few 'in-house' standards are adequate (I've written one of those too, but I know it is inadequate). For embedded systems (which is what I specialise in, and where software reliability is critical), there is a standard from The Motor Industry Software Reliability Association called MISRA C. MISRA C is now becoming more widely accepted outside of its original domain. It is defiantly not a style guide. Unfortunately you have to pay for it if you want to see the whole thing, but to give you an idea, there is an extract at http://www.misra.org.uk/graphics/miscprev.pdf. Some of MISRA C is probably only necessary in embedded or safety critical systems, but its philosophy, and much of its content is applicable to desktop applications as well (if all code were written like it were for a safety critical system, we'd have better quality software ... but pay much more). Unfortunately there is not yet a similar standard for C++, though a lot of MISRA C is of course applicable to C++.

    The important thing to understand about MISRA C and all coding standards that fit the definition I gave earlier, is that they are enforceable by automated rule checking (so there can be no slacking, or argument!). PC-Lint by Gimpel Software for example can check code against MISRA rules (http://www.gimpel.com/html/misra.htm). Using such a tool, may mean that you need not buy the MISRA C standard; although you'd have to blindly follow the rules without the detailed justification!. After a while, when you've cleared the sevaral thousand warnings your old code generated, you'll naturally code in a manner that passes the checks, and quality improves.

    Style guides are less important to good software; readability of unfamiliar code can be enhanced by syntax highlighting editors, and such editors are often capable or re-formatting the code to a preferred style. I cirrently use CodeWright for this, but actually prefer Visual SlickEdit. There are also standalone tools for formatting code, and these generally have more flexible options, but take some setting up if they are to be used to enforce standards compliance. Also you can make a rod for your own back with a style guide, since productivity can be enhanced by re-using non-conforming legacy code, or open source code, where you take what you can get.


    Clifford
    Last edited by clifford; September 1st, 2003 at 05:00 PM.
Page 2 of 2 First 12
  • Jump to page:

IMN logo majestic logo threadwatch logo seochat tools logo