一道C语言题

Beinggeeks 2015-03-24 04:24:06
#include <stdarg.h>
#include <stdio.h>

int ripple(int n, ...)
{
int i, j, k;
va_list p;

k = 0;
j = 1;
va_start(p, n);

for (; j < n; ++j)
{
i = va_arg(p, int);
for (; i; i &= i - 1)
++k;
}
va_end(p);
return k;
}

int main(void)
{
printf("%d\n", ripple(3, 5, 7));
return 0;
}


结果是5为什么?va_arg 、va_start等都是干什么用的
...全文
359 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2015-04-17
  • 打赏
  • 举报
回复
引用 6 楼 Beinggeeks 的回复:
[quote=引用 1 楼 zhao4zhong1 的回复:] va_arg, va_end, va_start Access variable-argument lists. type va_arg( va_list arg_ptr, type ); void va_end( va_list arg_ptr ); void va_start( va_list arg_ptr ); (UNIX version) void va_start( va_list arg_ptr, prev_param ); (ANSI version) Routine Required Header Optional Headers Compatibility va_arg <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT va_end <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT va_start <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT 1 Required for UNIX V compatibility. For additional compatibility information, see Compatibility in the Introduction. Libraries LIBC.LIB Single thread static library, retail version LIBCMT.LIB Multithread static library, retail version MSVCRT.LIB Import library for MSVCRT.DLL, retail version Return Value va_arg returns the current argument; va_start and va_end do not return values. Parameters type Type of argument to be retrieved arg_ptr Pointer to list of arguments prev_param Parameter preceding first optional argument (ANSI only) Remarks The va_arg, va_end, and va_start macros provide a portable way to access the arguments to a function when the function takes a variable number of arguments. Two versions of the macros are available: The macros defined in STDARG.H conform to the ANSI C standard, and the macros defined in VARARGS.H are compatible with the UNIX System V definition. The macros are: va_alist Name of parameter to called function (UNIX version only) va_arg Macro to retrieve current argument va_dcl Declaration of va_alist (UNIX version only) va_end Macro to reset arg_ptr va_list typedef for pointer to list of arguments defined in STDIO.H va_start Macro to set arg_ptr to beginning of list of optional arguments (UNIX version only) Both versions of the macros assume that the function takes a fixed number of required arguments, followed by a variable number of optional arguments. The required arguments are declared as ordinary parameters to the function and can be accessed through the parameter names. The optional arguments are accessed through the macros in STDARG.H or VARARGS.H, which set a pointer to the first optional argument in the argument list, retrieve arguments from the list, and reset the pointer when argument processing is completed. The ANSI C standard macros, defined in STDARG.H, are used as follows: All required arguments to the function are declared as parameters in the usual way. va_dcl is not used with the STDARG.H macros. va_start sets arg_ptr to the first optional argument in the list of arguments passed to the function. The argument arg_ptr must have va_list type. The argument prev_param is the name of the required parameter immediately preceding the first optional argument in the argument list. If prev_param is declared with the register storage class, the macro’s behavior is undefined. va_start must be used before va_arg is used for the first time. va_arg retrieves a value of type from the location given by arg_ptr and increments arg_ptr to point to the next argument in the list, using the size of type to determine where the next argument starts. va_arg can be used any number of times within the function to retrieve arguments from the list. After all arguments have been retrieved, va_end resets the pointer to NULL. The UNIX System V macros, defined in VARARGS.H, operate somewhat differently: Any required arguments to the function can be declared as parameters in the usual way. The last (or only) parameter to the function represents the list of optional arguments. This parameter must be named va_alist (not to be confused with va_list, which is defined as the type of va_alist). va_dcl appears after the function definition and before the opening left brace of the function. This macro is defined as a complete declaration of the va_alist parameter, including the terminating semicolon; therefore, no semicolon should follow va_dcl. Within the function, va_start sets arg_ptr to the beginning of the list of optional arguments passed to the function. va_start must be used before va_arg is used for the first time. The argument arg_ptr must have va_list type. va_arg retrieves a value of type from the location given by arg_ptr and increments arg_ptr to point to the next argument in the list, using the size of type to determine where the next argument starts. va_arg can be used any number of times within the function to retrieve the arguments from the list. After all arguments have been retrieved, va_end resets the pointer to NULL. Example /* VA.C: The program below illustrates passing a variable * number of arguments using the following macros: * va_start va_arg va_end * va_list va_dcl (UNIX only) */ #include <stdio.h> #define ANSI /* Comment out for UNIX version */ #ifdef ANSI /* ANSI compatible version */ #include <stdarg.h> int average( int first, ... ); #else /* UNIX compatible version */ #include <varargs.h> int average( va_list ); #endif void main( void ) { /* Call with 3 integers (-1 is used as terminator). */ printf( "Average is: %d\n", average( 2, 3, 4, -1 ) ); /* Call with 4 integers. */ printf( "Average is: %d\n", average( 5, 7, 9, 11, -1 ) ); /* Call with just -1 terminator. */ printf( "Average is: %d\n", average( -1 ) ); } /* Returns the average of a variable list of integers. */ #ifdef ANSI /* ANSI compatible version */ int average( int first, ... ) { int count = 0, sum = 0, i = first; va_list marker; va_start( marker, first ); /* Initialize variable arguments. */ while( i != -1 ) { sum += i; count++; i = va_arg( marker, int); } va_end( marker ); /* Reset variable arguments. */ return( sum ? (sum / count) : 0 ); } #else /* UNIX compatible version must use old-style definition. */ int average( va_alist ) va_dcl { int i, count, sum; va_list marker; va_start( marker ); /* Initialize variable arguments. */ for( sum = count = 0; (i = va_arg( marker, int)) != -1; count++ ) sum += i; va_end( marker ); /* Reset variable arguments. */ return( sum ? (sum / count) : 0 ); } #endif Output Average is: 3 Average is: 8 Average is: 0 Argument Access Routines See Also vfprintf
太高大上了,问题是我怎么能有耐心看懂它[/quote] 英语也是一门计算机语言的说。
fengidri 2015-03-25
  • 打赏
  • 举报
回复
这段代码是用于统计后面两个参数二进制形式下有多少个1
fly_dragon_fly 2015-03-25
  • 打赏
  • 举报
回复
va_arg 、va_start 需要一点点栈的知识,如果不明白,先补一下,如果明白,往下看 函数调用参数全部压栈,函数本身没法知道有几个参数,所以第一个n表示传了几个参数,看你的调用不对。 参数在栈中是连续的,va_start是根据n的地址得到下一个参数的地址 va_arg是得到当前参数,并且p'指向下一参数的地址,此处地址均指栈
Beinggeeks 2015-03-24
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
va_arg, va_end, va_start Access variable-argument lists. type va_arg( va_list arg_ptr, type ); void va_end( va_list arg_ptr ); void va_start( va_list arg_ptr ); (UNIX version) void va_start( va_list arg_ptr, prev_param ); (ANSI version) Routine Required Header Optional Headers Compatibility va_arg <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT va_end <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT va_start <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT 1 Required for UNIX V compatibility. For additional compatibility information, see Compatibility in the Introduction. Libraries LIBC.LIB Single thread static library, retail version LIBCMT.LIB Multithread static library, retail version MSVCRT.LIB Import library for MSVCRT.DLL, retail version Return Value va_arg returns the current argument; va_start and va_end do not return values. Parameters type Type of argument to be retrieved arg_ptr Pointer to list of arguments prev_param Parameter preceding first optional argument (ANSI only) Remarks The va_arg, va_end, and va_start macros provide a portable way to access the arguments to a function when the function takes a variable number of arguments. Two versions of the macros are available: The macros defined in STDARG.H conform to the ANSI C standard, and the macros defined in VARARGS.H are compatible with the UNIX System V definition. The macros are: va_alist Name of parameter to called function (UNIX version only) va_arg Macro to retrieve current argument va_dcl Declaration of va_alist (UNIX version only) va_end Macro to reset arg_ptr va_list typedef for pointer to list of arguments defined in STDIO.H va_start Macro to set arg_ptr to beginning of list of optional arguments (UNIX version only) Both versions of the macros assume that the function takes a fixed number of required arguments, followed by a variable number of optional arguments. The required arguments are declared as ordinary parameters to the function and can be accessed through the parameter names. The optional arguments are accessed through the macros in STDARG.H or VARARGS.H, which set a pointer to the first optional argument in the argument list, retrieve arguments from the list, and reset the pointer when argument processing is completed. The ANSI C standard macros, defined in STDARG.H, are used as follows: All required arguments to the function are declared as parameters in the usual way. va_dcl is not used with the STDARG.H macros. va_start sets arg_ptr to the first optional argument in the list of arguments passed to the function. The argument arg_ptr must have va_list type. The argument prev_param is the name of the required parameter immediately preceding the first optional argument in the argument list. If prev_param is declared with the register storage class, the macro’s behavior is undefined. va_start must be used before va_arg is used for the first time. va_arg retrieves a value of type from the location given by arg_ptr and increments arg_ptr to point to the next argument in the list, using the size of type to determine where the next argument starts. va_arg can be used any number of times within the function to retrieve arguments from the list. After all arguments have been retrieved, va_end resets the pointer to NULL. The UNIX System V macros, defined in VARARGS.H, operate somewhat differently: Any required arguments to the function can be declared as parameters in the usual way. The last (or only) parameter to the function represents the list of optional arguments. This parameter must be named va_alist (not to be confused with va_list, which is defined as the type of va_alist). va_dcl appears after the function definition and before the opening left brace of the function. This macro is defined as a complete declaration of the va_alist parameter, including the terminating semicolon; therefore, no semicolon should follow va_dcl. Within the function, va_start sets arg_ptr to the beginning of the list of optional arguments passed to the function. va_start must be used before va_arg is used for the first time. The argument arg_ptr must have va_list type. va_arg retrieves a value of type from the location given by arg_ptr and increments arg_ptr to point to the next argument in the list, using the size of type to determine where the next argument starts. va_arg can be used any number of times within the function to retrieve the arguments from the list. After all arguments have been retrieved, va_end resets the pointer to NULL. Example /* VA.C: The program below illustrates passing a variable * number of arguments using the following macros: * va_start va_arg va_end * va_list va_dcl (UNIX only) */ #include <stdio.h> #define ANSI /* Comment out for UNIX version */ #ifdef ANSI /* ANSI compatible version */ #include <stdarg.h> int average( int first, ... ); #else /* UNIX compatible version */ #include <varargs.h> int average( va_list ); #endif void main( void ) { /* Call with 3 integers (-1 is used as terminator). */ printf( "Average is: %d\n", average( 2, 3, 4, -1 ) ); /* Call with 4 integers. */ printf( "Average is: %d\n", average( 5, 7, 9, 11, -1 ) ); /* Call with just -1 terminator. */ printf( "Average is: %d\n", average( -1 ) ); } /* Returns the average of a variable list of integers. */ #ifdef ANSI /* ANSI compatible version */ int average( int first, ... ) { int count = 0, sum = 0, i = first; va_list marker; va_start( marker, first ); /* Initialize variable arguments. */ while( i != -1 ) { sum += i; count++; i = va_arg( marker, int); } va_end( marker ); /* Reset variable arguments. */ return( sum ? (sum / count) : 0 ); } #else /* UNIX compatible version must use old-style definition. */ int average( va_alist ) va_dcl { int i, count, sum; va_list marker; va_start( marker ); /* Initialize variable arguments. */ for( sum = count = 0; (i = va_arg( marker, int)) != -1; count++ ) sum += i; va_end( marker ); /* Reset variable arguments. */ return( sum ? (sum / count) : 0 ); } #endif Output Average is: 3 Average is: 8 Average is: 0 Argument Access Routines See Also vfprintf
太高大上了,问题是我怎么能有耐心看懂它
bear234 2015-03-24
  • 打赏
  • 举报
回复
百度: c语言 变参函数
小雷阵雨 2015-03-24
  • 打赏
  • 举报
回复
此题结果应该是2,你主函数里的函数传参的时候搞错了 ripple(3, 5, 7) 第一个参数表示的是 后面应该传递的参数个数 ,你这么写的意思就是告诉编译器你传递 3 个参数 而后面你只传递了两个参数,所以第一个参数应该是2 ripple(2, 5, 7) 。
william7_138 2015-03-24
  • 打赏
  • 举报
回复
这段程序的作用是用来计算出ripple()函数从第二个参数开始后面所有参数int形式的使用二进制表示时,每个二进制数中有多少个1,va_arg 、va_start是用来读取ripple()的可变参数的。
gqjjqg 2015-03-24
  • 打赏
  • 举报
回复
#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) ) #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //第一个可选参数地址 #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数地址 #define va_end(ap) ( ap = (va_list)0 ) // 将指针置为无效
赵4老师 2015-03-24
  • 打赏
  • 举报
回复
va_arg, va_end, va_start Access variable-argument lists. type va_arg( va_list arg_ptr, type ); void va_end( va_list arg_ptr ); void va_start( va_list arg_ptr ); (UNIX version) void va_start( va_list arg_ptr, prev_param ); (ANSI version) Routine Required Header Optional Headers Compatibility va_arg <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT va_end <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT va_start <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT 1 Required for UNIX V compatibility. For additional compatibility information, see Compatibility in the Introduction. Libraries LIBC.LIB Single thread static library, retail version LIBCMT.LIB Multithread static library, retail version MSVCRT.LIB Import library for MSVCRT.DLL, retail version Return Value va_arg returns the current argument; va_start and va_end do not return values. Parameters type Type of argument to be retrieved arg_ptr Pointer to list of arguments prev_param Parameter preceding first optional argument (ANSI only) Remarks The va_arg, va_end, and va_start macros provide a portable way to access the arguments to a function when the function takes a variable number of arguments. Two versions of the macros are available: The macros defined in STDARG.H conform to the ANSI C standard, and the macros defined in VARARGS.H are compatible with the UNIX System V definition. The macros are: va_alist Name of parameter to called function (UNIX version only) va_arg Macro to retrieve current argument va_dcl Declaration of va_alist (UNIX version only) va_end Macro to reset arg_ptr va_list typedef for pointer to list of arguments defined in STDIO.H va_start Macro to set arg_ptr to beginning of list of optional arguments (UNIX version only) Both versions of the macros assume that the function takes a fixed number of required arguments, followed by a variable number of optional arguments. The required arguments are declared as ordinary parameters to the function and can be accessed through the parameter names. The optional arguments are accessed through the macros in STDARG.H or VARARGS.H, which set a pointer to the first optional argument in the argument list, retrieve arguments from the list, and reset the pointer when argument processing is completed. The ANSI C standard macros, defined in STDARG.H, are used as follows: All required arguments to the function are declared as parameters in the usual way. va_dcl is not used with the STDARG.H macros. va_start sets arg_ptr to the first optional argument in the list of arguments passed to the function. The argument arg_ptr must have va_list type. The argument prev_param is the name of the required parameter immediately preceding the first optional argument in the argument list. If prev_param is declared with the register storage class, the macro’s behavior is undefined. va_start must be used before va_arg is used for the first time. va_arg retrieves a value of type from the location given by arg_ptr and increments arg_ptr to point to the next argument in the list, using the size of type to determine where the next argument starts. va_arg can be used any number of times within the function to retrieve arguments from the list. After all arguments have been retrieved, va_end resets the pointer to NULL. The UNIX System V macros, defined in VARARGS.H, operate somewhat differently: Any required arguments to the function can be declared as parameters in the usual way. The last (or only) parameter to the function represents the list of optional arguments. This parameter must be named va_alist (not to be confused with va_list, which is defined as the type of va_alist). va_dcl appears after the function definition and before the opening left brace of the function. This macro is defined as a complete declaration of the va_alist parameter, including the terminating semicolon; therefore, no semicolon should follow va_dcl. Within the function, va_start sets arg_ptr to the beginning of the list of optional arguments passed to the function. va_start must be used before va_arg is used for the first time. The argument arg_ptr must have va_list type. va_arg retrieves a value of type from the location given by arg_ptr and increments arg_ptr to point to the next argument in the list, using the size of type to determine where the next argument starts. va_arg can be used any number of times within the function to retrieve the arguments from the list. After all arguments have been retrieved, va_end resets the pointer to NULL. Example /* VA.C: The program below illustrates passing a variable * number of arguments using the following macros: * va_start va_arg va_end * va_list va_dcl (UNIX only) */ #include <stdio.h> #define ANSI /* Comment out for UNIX version */ #ifdef ANSI /* ANSI compatible version */ #include <stdarg.h> int average( int first, ... ); #else /* UNIX compatible version */ #include <varargs.h> int average( va_list ); #endif void main( void ) { /* Call with 3 integers (-1 is used as terminator). */ printf( "Average is: %d\n", average( 2, 3, 4, -1 ) ); /* Call with 4 integers. */ printf( "Average is: %d\n", average( 5, 7, 9, 11, -1 ) ); /* Call with just -1 terminator. */ printf( "Average is: %d\n", average( -1 ) ); } /* Returns the average of a variable list of integers. */ #ifdef ANSI /* ANSI compatible version */ int average( int first, ... ) { int count = 0, sum = 0, i = first; va_list marker; va_start( marker, first ); /* Initialize variable arguments. */ while( i != -1 ) { sum += i; count++; i = va_arg( marker, int); } va_end( marker ); /* Reset variable arguments. */ return( sum ? (sum / count) : 0 ); } #else /* UNIX compatible version must use old-style definition. */ int average( va_alist ) va_dcl { int i, count, sum; va_list marker; va_start( marker ); /* Initialize variable arguments. */ for( sum = count = 0; (i = va_arg( marker, int)) != -1; count++ ) sum += i; va_end( marker ); /* Reset variable arguments. */ return( sum ? (sum / count) : 0 ); } #endif Output Average is: 3 Average is: 8 Average is: 0 Argument Access Routines See Also vfprintf

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧