2

在我的 NC30 M16C 编译器版本 5 中,我有以前的程序员使用的以下宏。我们在“printf()”、“sprintf()”等函数中使用这个宏。

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 );

这是我们使用这些 micros 的功能之一。此函数与“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;
}

请指导我,我应该怎么做才能纠正这个问题。

提前致谢。

4

1 回答 1

0

您可以尝试替换:

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

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

解释:

您会收到编译错误,因为此表达式:

((type *) args )++

在 C 中无效:强制转换的结果不是左值,并且后缀++运算符要求其操作数是左值。许多编译器对这个约束很松懈,但显然你的不是(或者新版本更严格)。

另请注意,建议的解决方法应该在您的程序中使用简单的赋值表达式,例如:

unum = va_arg( args, unsigned int );

因为=比逗号运算符具有更高的优先级。

编辑

另一个(也许更好)解决方案:您应该能够使用此解决方案绕过强制转换结果不是左值的事实:

#define va_arg( args, type ) *( *(type **) &args )++
于 2012-08-02T23:16:08.270 回答