Shop OBEX P1 Docs P2 Docs Learn Events
Temporary leave... - Page 4 — Parallax Forums

Temporary leave...

124»

Comments

  • Kevin WoodKevin Wood Posts: 1,266
    edited 2011-10-18 01:44
    RiJoRi wrote:
    Of course, each compiler has its own oddities: The HPC compiler will accept loop(n) {}, which -- as far as I know -- no other C compiler will accept.

    The cool thing is that it can still be done with other compilers...
    #include <stdio.h>
    
    #define loop(x) int i; for (i = 1; i <= x; i++)
    
    int main(void) {
        
        loop(5) {
            printf("%i : it works...\n", i);    
        }
        return(0);
    }
    
    I tested it with GCC & Ch on Linux. Somebody else would need to try it with Catalina or compiler of choice.
  • TorTor Posts: 2,010
    edited 2011-10-18 02:35
    For strict ANSI or C89 compilers you would get into some trouble though.. as soon as you add some other code before using loop(). That's because variables can't be declared after code. Something slightly hackish like this can work around it though:
    #include <stdio.h>
    
    static int _xyzxyx;
    #define loop(x) for (_xyzxyx = 0; _xyzxyx < x; _xyzxyx++)
    
    int main (void) {
        int test = 0;
        /*
         * Add some code, this would trigger a problem with ANSI with the
         * original version
         */
        printf ("Starting here\n"); 
        loop(5) {
              printf ("%d it works...\n", ++test);
        }
        return (0);
    }
    

    But having that helper global variable isn't all nice, it would leave a bad taste in the mouth if you try to put the loop define in a header file, for example.

    If all you want to use is GCC or modern C9x compilers then there aren't any problems, of course.

    -Tor
  • RossHRossH Posts: 5,519
    edited 2011-10-18 03:03
    Kevin Wood wrote: »
    The cool thing is that it can still be done with other compilers...
    #include <stdio.h>
    
    #define loop(x) int i; for (i = 1; i <= x; i++)
    
    int main(void) {
        
        loop(5) {
            printf("%i : it works...\n", i);    
        }
        return(0);
    }
    
    I tested it with GCC & Ch on Linux. Somebody else would need to try it with Catalina or compiler of choice.

    This works with Catalina ... but it is just a coincidence. You will see the problem if you put any executable statement before the "loop". For example:
    #include <stdio.h>
    
    #define loop(x) int i; for (i = 1; i <= x; i++)
    
    int main(void) {
    
        [COLOR=red]printf ("Starting...\n");[/COLOR]
        
        loop (5) { 
            printf("%i : it works...\n", i);    
        }
        return(0);
    }
    
    This will throw a compilation error on a C89 compiler. C89 requires an additional set of curly brackets around a declaration that appears in the middle of a statement block (in this case, the declaration "int i").

    However, the following slight modification will work on any C compiler:
    #include <stdio.h>
    
    #define loop(x) [COLOR=red]{[/COLOR] int i; for (i = 1; i <= x; i++)
    
    int main(void) {
    
        printf ("Starting...\n");
        
        loop (5) { 
            printf("%i : it works...\n", i);    
        }[COLOR=red]}[/COLOR]
        return(0);
    }
    
    The ability to mix declarations and statements without requiring another curly bracket was one of the minor differences between C89 and C99 - but this is one that is quite useful, so many C compilers implement it. I may one day add it to Catalina (it has already been added to several other LCC-based compilers). However, it is not very high on my list of priorities, since all it really saves you is the cost of typing a another curly bracket.

    Ross.

    EDIT: I see Tor beat me to it - but I think my solution is better :)
  • TorTor Posts: 2,010
    edited 2011-10-18 03:43
    RossH wrote: »
    EDIT: I see Tor beat me to it - but I think my solution is better :)
    I thought of that one, but rejected it because it needs that extra '}' which makes the usage different from a proper language-defined loop(). It will also mess up auto-indentation in editors that support it (because it becomes unbalanced).

    Here's another version for strict ANSI compilers.. it uses a function though.
    #include <stdio.h>
    
    static int loopf (int x) {
        static int y;
        if (y == 0)
    	y = x+1;
        return (--y);
    }
    
    #define loop(x) while (loopf(x))
    
    int main (void) {
        int test = 0;
    
        loop(5) {
              printf ("%d it works...\n", ++test);
        }
    
        loop(4)
    	printf ("Hey\n");
        return (0);
    }
    
  • RossHRossH Posts: 5,519
    edited 2011-10-18 04:14
    Tor wrote: »
    I thought of that one, but rejected it because it needs that extra '}' which makes the usage different from a proper language-defined loop(). It will also mess up auto-indentation in editors that support it (because it becomes unbalanced).

    Here's another version for strict ANSI compilers.. it uses a function though.
    ...

    Clever! I agree the extra } is a pain - but my solution supports nested loops, whereas yours does not (because of the static declaration).

    Also, if you don't like }}, you can #define endloop }}

    Ross.
  • TorTor Posts: 2,010
    edited 2011-10-18 04:43
    RossH wrote: »
    Clever! I agree the extra } is a pain - but my solution supports nested loops, whereas yours does not (because of the static declaration).
    You're right about that, nested loops are not unimportant. Will see if there's a fix for that too.. ;)

    -Tor
  • Kevin WoodKevin Wood Posts: 1,266
    edited 2011-10-18 05:13
    If I compile the "bad" examples with... gcc -std=c89 scratch.c -o scratch ...it still compiles fine.

    If I compile with... gcc -pedantic -std=c89 scratch.c -o scratch ...it fails with...
    scratch.c: In function &#8216;main&#8217;:
    scratch.c:9: warning: ISO C90 forbids mixed declarations and code
    

    If I use clang/llvm ... clang -std=c89 scratch.c -o scratch ... compiles...

    if I add -pedantic, this is the error it gives...
    scratch.c:9:5: warning: ISO C90 forbids mixing declarations and code [-Wdeclaration-after-statement]
        loop(5) {
        ^
    scratch.c:3:21: note: instantiated from:
    #define loop(x) int i; for (i = 1; i <= x; i++)
                        ^
    1 warning generated.
    
  • TorTor Posts: 2,010
    edited 2011-10-18 05:37
    Yep. With MIPSPro C 2.1 (SGI, not the latest compiler) we get:
    >cc -c loop.c
    "loop.c", line 14: error(1241): declaration may not appear after executable
              statement in block
          int i;
          ^
    
    1 error detected in the compilation of "loop.c".
    
    And with IBM VisualAge C v5 we get:
    "loop.c", line 14.5: 1506-275 (S) Unexpected text 'int' encountered.
    "loop.c", line 14.9: 1506-045 (S) Undeclared identifier i.
    
    Later versions of both compilers handle late-declared variables though, which certainly makes certain things easier (but can be abused as well, as is often the case when features are added).

    -Tor
  • Heater.Heater. Posts: 21,230
    edited 2011-10-18 05:53
    You know, RavenKallen was about to suspend Propeller operations so as to dedicate time to learning C.

    And now his thread has a long treatise on the use of C macros. Not only is this seriously over the top for a beginner in C the use of macros in this way, to create a loop construct for example, is seriously frowned upon in the C community.
  • prof_brainoprof_braino Posts: 4,313
    edited 2011-10-18 06:24
    Heater. wrote: »
    ... seriously over the top... is seriously frowned upon in the C community.

    Appearantly not in this community :)

    Ravenkallen is getting a taste of what he'll encounter with his new-found mastery of C

    Maybe we could suggest peer reviews, at least to get feedback as to what is good practice and what might cause issues?
  • TorTor Posts: 2,010
    edited 2011-10-18 07:08
    Heater. wrote: »
    You know, RavenKallen was about to suspend Propeller operations so as to dedicate time to learning C.

    And now his thread has a long treatise on the use of C macros. Not only is this seriously over the top for a beginner in C the use of macros in this way,
    True - it's fun to discuss such things, but it probably belongs in a different thread.

    *
    to create a loop construct for example, is seriously frowned upon in the C community.
    Right, except for the 'do while (0)* trick :-)

    -Tor
  • Heater.Heater. Posts: 21,230
    edited 2011-10-18 08:34
    Err yeah...and except for what I have done to create threads using an extension to GCC that allows void pointers to point to labels and then gotos the pointers.

    See "labels as values" here : http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
  • TorTor Posts: 2,010
    edited 2011-10-18 15:14
    Heater. wrote: »
    Err yeah...and except for what I have done to create threads using an extension to GCC that allows void pointers to point to labels and then gotos the pointers.

    See "labels as values" here : http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
    Hey, computed gotos.. aka Fortran assigned gotos! Good old times!

    "Since Fortran doesn't have a structured IF, REPEAT ... UNTIL, or CASE statement, Real Programmers don't have to worry about not using them. Besides, they can be simulated when necessary using assigned GOTOs."
    -- from 'Real Programmers Don't Use Pascal', letter to Datamation magazine, July 1983)

    -Tor
  • RossHRossH Posts: 5,519
    edited 2011-10-18 16:10
    Heater. wrote: »
    Err yeah...and except for what I have done to create threads using an extension to GCC that allows void pointers to point to labels and then gotos the pointers.

    See "labels as values" here : http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html

    Isn't C great? You can do literally anything. This is of course the great virtue of C, and the reason that after 30 years, it is still so popular as both an embedded language and as a systems programming language.

    But the price you pay for this power and flexibility is complexity and (sometimes) portability.

    To bring this back to the original reason for this thread (which was that Ravenkallen wanted to learn C), I think an important part of learning C is understanding this tradeoff.

    If the prospect of the complexity of C scares you, then you probably shouldn't be learning it. If the prospect of the power of C excites you, then you probably should!

    Ross.
Sign In or Register to comment.