Thread: problem with gcc or with my brain

  1. #1
    Registered User
    Join Date
    Sep 2002
    Posts
    3

    problem with gcc or with my brain

    Hi Folks !

    I have a problem with a source witch do not compile right.
    Compiler is gcc on an embedded system.

    I think the examples #2 & #3 must be generate the same code,
    but the gcc donīt like it :-(
    Gcc aborts with the error : invalid use of non-lvalue array

    I need the function call like the example #3.
    Can me help someone, please !!!

    this is the source:

    void join(char *strings[],char *dest,int num)
    {
    int i;

    for (i=0;i<num;i++)
    dest=strcpy(dest,strings[i])+strlen(strings[i]);
    }

    void test(void)
    {
    char *string2="Var2",joined[80];
    char *this_works[]={"Const1",string2,"Const3"};

    join((char *[]{"Const1","Const2","Const3"},joined,3); /* #1 */
    join(this_works,joined,3); /* #2 */
    join((char *[]){"Const1",string2,"Const3"},joined,3); /* #3 */
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    How many ANSI rules are you willing to break, and how many gcc specific extensions are you willing to use?

    Because in ANSI-C there is very little in the test function which is actually valid.

    > char *this_works[]={"Const1",string2,"Const3"};
    sample.c:16: warning: initializer element is not computable at load time

    > join((char *[]){"Const1","Const2","Const3"},joined,3);
    sample.c:18: warning: ISO C89 forbids compound literals

    > join((char *[]){"Const1",string2,"Const3"},joined,3);
    sample.c:20: warning: ISO C89 forbids compound literals
    sample.c:20: invalid use of non-lvalue array

    Here's an alternative approach
    Code:
    void join ( char *dest, int num, ... ) {
        int i;
        va_list  ap;
        va_start(ap,num);
    
        for(i=0;i<num;i++) {
            char    *p = va_arg(ap,char*);
            strcpy(dest,p);
            dest += strlen(p);
        }
        va_end(ap);
    }
    
    void test(void) {
        char *string2="Var2";
        char joined[80];
    
        join( joined, 3, "Const1","Const2","Const3" );
        printf( "Joined=%s\n", joined );
        join( joined, 3, "Const1",string2,"Const3" );
        printf( "Joined=%s\n", joined );
    }
    I might suggest that you use sprintf to catenate multiple strings, but since you said embedded system, you might not want all the standard library dragged into the system.
    On the other hand, if it's already there, may as well use it.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Sep 2002
    Posts
    3
    Originally posted by Salem
    How many ANSI rules are you willing to break, and how many gcc specific extensions are you willing to use?

    Because in ANSI-C there is very little in the test function which is actually valid.

    > char *this_works[]={"Const1",string2,"Const3"};
    sample.c:16: warning: initializer element is not computable at load time

    > join((char *[]){"Const1","Const2","Const3"},joined,3);
    sample.c:18: warning: ISO C89 forbids compound literals

    > join((char *[]){"Const1",string2,"Const3"},joined,3);
    sample.c:20: warning: ISO C89 forbids compound literals
    sample.c:20: invalid use of non-lvalue array

    Here's an alternative approach
    Code:
    void join ( char *dest, int num, ... ) {
        int i;
        va_list  ap;
        va_start(ap,num);
    
        for(i=0;i<num;i++) {
            char    *p = va_arg(ap,char*);
            strcpy(dest,p);
            dest += strlen(p);
        }
        va_end(ap);
    }
    
    void test(void) {
        char *string2="Var2";
        char joined[80];
    
        join( joined, 3, "Const1","Const2","Const3" );
        printf( "Joined=%s\n", joined );
        join( joined, 3, "Const1",string2,"Const3" );
        printf( "Joined=%s\n", joined );
    }
    I might suggest that you use sprintf to catenate multiple strings, but since you said embedded system, you might not want all the standard library dragged into the system.
    On the other hand, if it's already there, may as well use it.

    Thanks for your reply, but i have some limitations on my target:

    - printf(),scanf() and variants are not available.
    - the function join() should be inside a library but the system allows only functions with fixed number of arguments.
    - but i can use all gcc specific extensions.

    So i can't use va_arg :-(

  4. #4
    Registered User moi's Avatar
    Join Date
    Jul 2002
    Posts
    946
    Originally posted by neo51
    Thanks for your reply, but i have some limitations on my target:

    - printf(),scanf() and variants are not available.
    - the function join() should be inside a library but the system allows only functions with fixed number of arguments.
    - but i can use all gcc specific extensions.

    So i can't use va_arg :-(
    what gcc implimentation doesnt have va_arg?

    edit: doh i didn't read the embedded system part
    hello, internet!

  5. #5
    KingoftheWorld
    Guest
    Originally posted by neo51
    Thanks for your reply, but i have some limitations on my target:

    - printf(),scanf() and variants are not available.
    - the function join() should be inside a library but the system allows only functions with fixed number of arguments.
    - but i can use all gcc specific extensions.

    So i can't use va_arg :-(
    What your target computer or device you code will run on?
    Does your gcc complier install on SunOS or Solaris?

    KingoftheWorld

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Well given those rules, how about this
    Using varargs in the gcc pre-processor

    Code:
    #include <stdio.h>
    #include <string.h>
    
    // count the elements in an array
    #define ASIZE(x)        (sizeof(x)/sizeof(x[0]))
    
    // initialise a local array of string pointers, and call join()
    #define JOINER(dest,strings...) { \
        char *temp[] = { "", ## strings }; \
        join( temp, dest, ASIZE(temp) ); \
    }
    
    void join(char *strings[],char *dest,int num) {
        int i;
    
        for(i=0;i<num;i++)
            dest=strcpy( dest,strings[i] )+strlen( strings[i] );
    }
    
    void test(void) {
        char *string2="Var2",joined[80];
    
        JOINER(joined);
        printf( "'%s'\n", joined );
        JOINER(joined,"Const1","Const2","Const3");
        printf( "'%s'\n", joined );
        JOINER(joined,"Const1",string2,"Const3");
        printf( "'%s'\n", joined );
    }
    
    int main( ) {
        test( );
        return 0;
    }
    You can remove
    "", ##
    from the temp array in the macro if you can guarantee that you'll always pass parameters to the macro.

    On the plus side, you no longer have to remember to change the count each time you change the number of parameters in a call.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Sep 2002
    Posts
    3
    Originally posted by Salem
    Well given those rules, how about this
    Using varargs in the gcc pre-processor

    Code:
    #include <stdio.h>
    #include <string.h>
    
    // count the elements in an array
    #define ASIZE(x)        (sizeof(x)/sizeof(x[0]))
    
    // initialise a local array of string pointers, and call join()
    #define JOINER(dest,strings...) { \
        char *temp[] = { "", ## strings }; \
        join( temp, dest, ASIZE(temp) ); \
    }
    
    void join(char *strings[],char *dest,int num) {
        int i;
    
        for(i=0;i<num;i++)
            dest=strcpy( dest,strings[i] )+strlen( strings[i] );
    }
    
    void test(void) {
        char *string2="Var2",joined[80];
    
        JOINER(joined);
        printf( "'%s'\n", joined );
        JOINER(joined,"Const1","Const2","Const3");
        printf( "'%s'\n", joined );
        JOINER(joined,"Const1",string2,"Const3");
        printf( "'%s'\n", joined );
    }
    
    int main( ) {
        test( );
        return 0;
    }
    You can remove
    "", ##
    from the temp array in the macro if you can guarantee that you'll always pass parameters to the macro.

    On the plus side, you no longer have to remember to change the count each time you change the number of parameters in a call.

    Salem, thanks for this nice code :-))

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Quick Compilation Question
    By chacham15 in forum C Programming
    Replies: 10
    Last Post: 10-12-2008, 08:15 PM
  2. Profiler Valgrind
    By afflictedd2 in forum C++ Programming
    Replies: 4
    Last Post: 07-18-2008, 09:38 AM
  3. Replies: 4
    Last Post: 09-02-2007, 08:47 PM
  4. Compiles on gcc 3.3 but not on gcc 4.0.3
    By cunnus88 in forum C++ Programming
    Replies: 5
    Last Post: 03-29-2007, 12:24 PM
  5. Bin packing problem....
    By 81N4RY_DR460N in forum C++ Programming
    Replies: 0
    Last Post: 08-01-2005, 05:20 AM