2012-08-02 45 views
2

在我的NC30 M16C編譯器版本5中,我使用了以前的程序員使用的以下宏。我們在「printf()」,「sprintf()」等函數中使用這個宏。升級NC30 M16 C編譯器:va_arg問題

typedef unsigned char * va_list; 
#define va_start(args, first) args = (va_list) ((unsigned short) &first + sizeof(first)) 
#define va_arg(args, type) *((type *) args)++ 
#define va_end(args) 

當我用NC30 M16C編譯器版本6編譯此代碼時,它給我錯誤「無效的左值」。 這裏是整個錯誤消息的一部分:

clib.c(253) : C2700 (E) invalid lvalue 
===> unum = va_arg(args, unsigned int); 
clib.c(293) : C2700 (E) invalid lvalue 
===> fch = va_arg(args, far char *); 
clib.c(299) : C2700 (E) invalid lvalue 
===> nch = va_arg(args, char *); 
clib.c(305) : C2700 (E) invalid lvalue 
===> unum = va_arg(args, unsigned int); 
clib.c(323) : C2700 (E) invalid lvalue 
===> ulong = va_arg(args, unsigned long); 
clib.c(341) : C2700 (E) invalid lvalue 
===> llong = va_arg(args, unsigned long long); 
clib.c(359) : C2700 (E) invalid lvalue 
===> ulong = va_arg(args, unsigned long); 
clib.c(377) : C2700 (E) invalid lvalue 
===> unum = va_arg(args, unsigned short); 
clib.c(382) : C2700 (E) invalid lvalue 
===> ft = va_arg(args, float); 
clib.c(519) : C2694 (E) unknown variable source 
===> *source++ = zeropad ? '0' : ' '; 
clib.c(527) : C2694 (E) unknown variable source 
===> *source++ = '%'; 
clib.c(532) : C2700 (E) invalid lvalue 
===> snum = va_arg(args, signed int); 
clib.c(550) : C2694 (E) unknown variable source 
===>  *source++ = *tempptr; 
clib.c(556) : C2700 (E) invalid lvalue 
===> fch = va_arg(args, far char *); 
clib.c(558) : C2694 (E) unknown variable source 
===>  *source++ = *fch++; 
clib.c(564) : C2700 (E) invalid lvalue 
===> nch = va_arg(args, char *); 
clib.c(566) : C2694 (E) unknown variable source 
===>  *source++ = *nch++; 
clib.c(572) : C2700 (E) invalid lvalue 
===> unum = va_arg(args, unsigned int); 

這裏是在其中我們使用這些萬分之一的功能中的一個。此功能是相同的功能的「printf」,但將其命名爲zwPrintf():

int zwPrintf(far char * format, ...) { 
    zwVAList args; 
    unsigned int unum; 
    unsigned char temp[ FIELD_BUFF_SIZE + 1 ];  /* for formatting numbers (max length for long decimal) */ 
    unsigned char * tempptr; 
    int zeropad, minfield, counter; 
    far char * fch; 
    char * nch; 
    unsigned long ulong; 
    int negative; 
    float ft, mantissa; 
    unsigned long long llong; 
    //unsigned char mychar; 
    //unsigned char *mychar_p; 
    //unsigned int *mytest_p; 

    va_start(args, format); 

    while(*format) { 
     if(*format == '%') { 
      format++; 
      zeropad = 0; 
      minfield = 0; 
      negative = 0; 
      if(*format == '0') 
       zeropad = 1;   /* we want zero padding to field width */ 
      while(*format >= '0' && *format <= '9') { 
       /* we are specifying field width */ 
       minfield *= 10; 
       minfield += *format - '0'; 
       format++; 
      } 
      if(minfield > FIELD_BUFF_SIZE) {  /* we want a field width greater than our field buffer, pad misc */ 
       for(counter = 0; counter < minfield - FIELD_BUFF_SIZE; counter++) 
        zwPutc((unsigned char) (zeropad ? '0' : ' ')); 
       minfield = FIELD_BUFF_SIZE; 
      } 
      switch(*format) { 
       case '%': /* literal % */ 
        zwPutc('%'); 
       break; 

       case 'd': /* signed decimal output */ 
        unum = va_arg(args, unsigned int);  /* pull unsigned, and do math ourselves (to avoid confusion) */ 

        //mychar='a'; 
        //mychar_p = &mychar; 
        //mytest_p = ((unsigned int*)mychar_p); 
        //mytest_p++; 
        //unum = *mytest_p; 
        //unum = (*((unsigned int*)args))++; 
        //unum = (*((unsigned int*)args))++; 

        /* convert to decimal (backward) */ 
        if(unum >= 0x8000) {  /* number is -'ve */ 
         negative = 1; 
         unum = ~unum + 1;   /* make number +'ve */ 
        } 

        tempptr = &temp[ FIELD_BUFF_SIZE ]; 
        counter = 0; 
        do { 
         if(unum) 
          *tempptr-- = (unum % 10) + '0'; 
         else { 
          if(negative && (zeropad == 0)) { 
           *tempptr-- = '-'; 
           negative = 0; 
          } 
          else 
           *tempptr-- = (zeropad || counter == 0) ? '0' : ' '; 
         } 
         unum /= 10; 
         counter++; 
        } while(unum || counter < minfield); 
        /* output the string */ 
        if(negative) 
         zwPutc('-'); 
        for(tempptr++; tempptr <= &temp[ FIELD_BUFF_SIZE ]; tempptr++) 
         zwPutc(*tempptr); 
       break; 

       case 's': /* far char * */ 
        fch = va_arg(args, far char *); 
        while(*fch) 
         zwPutc(*fch++); 
       break; 

       case 'S': /* near char * (extension) */ 
        nch = va_arg(args, char *); 
        while(*nch) 
         zwPutc(*nch++); 
       break; 

       case 'x': /* hexadecimal */ 
        unum = va_arg(args, unsigned int); 
        /* convert to hexadecimal (backward) */ 
        tempptr = &temp[ FIELD_BUFF_SIZE ]; 
        counter = 0; 
        do { 
         if(unum) 
          *tempptr-- = zwHexToAsc((unsigned char) unum & 0x0F); 
         else 
          *tempptr-- = (zeropad || counter == 0) ? '0' : ' '; 
         unum >>= 4; 
         counter++; 
        } while(unum || counter < minfield); 
        /* output the string */ 
        for(tempptr++; tempptr <= &temp[ FIELD_BUFF_SIZE ]; tempptr++) 
         zwPutc(*tempptr); 
       break; 

       case 'i': /* unsigned long int decimal (extension) */ 
        ulong = va_arg(args, unsigned long); 
        /* convert to decimal (backward) */ 
        tempptr = &temp[ FIELD_BUFF_SIZE ]; 
        counter = 0; 
        do { 
         if(ulong) 
          *tempptr-- = (unsigned char)(ulong % 10) + '0'; 
         else 
          *tempptr-- = (zeropad || counter == 0) ? '0' : ' '; 
         ulong /= 10; 
         counter++; 
        } while(ulong || counter < minfield); 
        /* output the string */ 
        for(tempptr++; tempptr <= &temp[ FIELD_BUFF_SIZE ]; tempptr++) 
         zwPutc(*tempptr); 
       break; 

       case 'L': /* unsigned long long decimal (extension) */ 
        llong = va_arg(args, unsigned long long); 
        /* convert to decimal (backward) */ 
        tempptr = &temp[ FIELD_BUFF_SIZE ]; 
        counter = 0; 
        do { 
         if(llong) 
          *tempptr-- = (unsigned char)(llong % 10) + '0'; 
         else 
          *tempptr-- = (zeropad || counter == 0) ? '0' : ' '; 
         llong /= 10; 
         counter++; 
        } while(llong || counter < minfield); 
        /* output the string */ 
        for(tempptr++; tempptr <= &temp[ FIELD_BUFF_SIZE ]; tempptr++) 
         zwPutc(*tempptr); 
       break; 

       case 'h': /* unsigned long int hexadecimal (extension) */ 
        ulong = va_arg(args, unsigned long); 
        /* convert to hexadecimal (backward) */ 
        tempptr = &temp[ FIELD_BUFF_SIZE ]; 
        counter = 0; 
        do { 
         if(ulong) 
          *tempptr-- = zwHexToAsc(((unsigned char) ulong) & 0x0F); 
         else 
          *tempptr-- = (zeropad || counter == 0) ? '0' : ' '; 
         ulong >>= 4; 
         counter++; 
        } while(ulong || counter < minfield); 
        /* output the string */ 
        for(tempptr++; tempptr <= &temp[ FIELD_BUFF_SIZE ]; tempptr++) 
         zwPutc(*tempptr); 
       break; 

       case 'c': 
        unum = va_arg(args, unsigned short); 
        zwPutc((char) unum); 
       break; 

       case 'f': 
        ft = va_arg(args, float); 
#if 0 
        /* convert to decimal (backward) */ 
        if(ft < 0) {  /* number is -'ve */ 
         negative = 1; 
         ft = -ft; 
        } 

        tempptr = &temp[ FIELD_BUFF_SIZE ]; 
        counter = 0; 

        /* split float to integer and mantissa part */ 
        ulong = ft/1; 
        mantissa = ft - (float)ulong; 

        /* get integer part */ 
        do { 
         if(ulong){ 
          *tempptr-- = (unsigned char)(ulong % 10) + '0'; 
         } 
         else { 
          *tempptr-- = (zeropad || counter == 0) ? '0' : ' '; 
         } 
         ulong /= 10; 
         counter++; 
        } while(ulong || counter < minfield); 

        if (negative) { 
         temp[ 0 ] = '-'; 
         zwMemcpy(&temp[ 1 ], &temp[ FIELD_BUFF_SIZE - counter ], counter);  //change to right position 
         counter++; 
        } 
        else 
         zwMemcpy(&temp[ 0 ], &temp[ FIELD_BUFF_SIZE - counter ], counter); 

        temp[ counter++ ] = '.';       

        /* get mantissa part */ 
        tempptr = &temp[ counter ]; 
        do { 
         unum = (mantissa * 10)/1; 
         if(unum){ 
          *tempptr++ = (unsigned char)(unum) + '0';  
         } 
         else { 
          *tempptr++ = '0'; 
         } 

         mantissa = (float) (mantissa * 10.0 - (float)unum) * 10.0;       
         counter++; 
        } while(mantissa > 0 || counter < minfield); 


        for(unum = 0; unum < counter; unum++) 
         zwPutc(temp[ unum ]); 

        /* convert to decimal (backward) */ 
        if(ft < 0) {  /* number is -'ve */ 
         negative = 1; 
         ft = -ft; 
        } 

        tempptr = &temp[ FIELD_BUFF_SIZE ]; 
        counter = 0; 
        do { 
         if(ft >= 1.0){ 
          *tempptr-- = (ft % 10.0) + '0'; 
//       *tempptr-- = (ft * 10 - ((ft * 100)/10)) + '0'; 
         } 
         else { 
          if(negative && (zeropad == 0)) { 
           *tempptr-- = '-'; 
           negative = 0; 
          } 
          else 
           *tempptr-- = (zeropad || counter == 0) ? '0' : ' '; 
         } 
         ft /= 10; 
         counter++; 
        } while(ft >= 1.0 || counter < minfield); 

        /* output the string */ 
        if(negative) 
         zwPutc('-'); 

        for(tempptr++; tempptr <= &temp[ FIELD_BUFF_SIZE ]; tempptr++) 
         zwPutc(*tempptr); 
#endif 
       break; 

       case 0:  /* end of string (malformed string anyway) */ 
        va_end(args); 
        return -1;  /* error */ 
       break; 
      } 
     } 
     else 
      zwPutc(*format); 

     format++; 
    } 

    va_end(args); 

    return -1; 
} 

請指引我,我應該怎麼做才能解決這個問題。

在此先感謝。

+0

顯示我們調用這些宏的代碼。 (我認爲你的實現不提供''?) – 2012-08-02 23:02:40

+0

實際上錯誤消息是有道理的,gcc是這個鬆懈的,但是轉換的結果不是左值,所以postfix ++不能應用(違反約束)。 – ouah 2012-08-02 23:09:18

+0

我在原來的帖子裏增加了一個功能,它使用這些micros。謝謝。 – user977601 2012-08-03 03:09:24

回答

0

你能不能嘗試更換:

#define va_arg(args, type) *((type *) args)++ 

#define va_arg(args, type) *((type *) args), args += sizeof (type) 

說明:

你得到的編譯錯誤,因爲這個表達式:

((type *) args)++ 

是無效C:r演員的表演不是左值,後綴++操作符要求其操作數爲左值。很多編譯器都有這個限制,但顯然你的不是(或者新版本更嚴格)。

還要注意,所提出的解決辦法應該在你的程序簡單賦值表達式工作,如:

unum = va_arg(args, unsigned int); 

因爲=比逗號運算符優先級越高。

編輯

另一個(甚至更好)的解決方案:你應該能夠繞過事實鑄造的結果是不使用這一解決方案的左值:

#define va_arg(args, type) *(*(type **) &args)++ 
+0

你的第一個建議返回錯誤的值,你需要更多的東西'#define va_arg(args,type)(args + = sizeof(type),((type *)args)[ - 1])' – 2012-08-03 00:56:06

+0

謝謝。 我嘗試了兩個。它編譯得很好,但不會在我的圖形LCD上顯示任何內容。可能是因爲「printf」,「sprintf」等功能使用這三個宏。而有些東西還是不對的。 – user977601 2012-08-03 02:07:21

+0

@ChrisDodd我認爲你剛纔解決方案後沒有閱讀註解。我沒有在整個宏表達式之間添加parens:如果宏只與'unum = va_arg(args,unsigned int)'這樣的表達式一起使用;'它會工作,因爲賦值操作將在第一個操作數的逗號運算符。當然更復雜的是:'unum = va_arg(args,unsigned int)+某事;'它會失敗。我的答案中的第二個建議沒有這個問題。 – ouah 2012-08-03 08:09:28