命令行参数和变长参数表

程序的主函数main的参数叫做命令行参数,他们是程序在运行时的输入数据,其参数个数是可变的。

除了main函数之外的函数,其参数个数也可以是可变的,这就是变长参数表。


    在进程中,程序中栈的方向都是从高地址到低地址扩展的,即栈底在高处。C语言函数参数采用自右向左的入栈顺序,一个原因就是为了支持可变长参数形式。这样使得右边的参数先入栈,在高地址,从最左边的参数开始只需做地址加法就能找到其他参数。

main主函数获取命令行参数

下面是主函数从高地址到低地址的栈结构:
0xc0000000:栈底
0xbffffffc:NULL(0x00000000)
程序名称字符串值 *
环境变量字符串值 *
命令行参数字符串值 *
ELF Auxiliary Vectors
NULL(结束envp[])
环境变量字符串地址列表(envp[])
NULL(结束argv[])
命令行参数字符串地址列表(argv[])
%esp:命令行参数个数(dword argc)


int main(int argc, char** argv)
或者
int main(int argc, char* argv[])

1、标准的命令行参数获取方法
argc是命令行参数个数,argv是指向各个参数的指针数组。
#include <stdio.h>

int main(int argc, char ** argv)
{
int i;
for (i=0; i < argc; i++)
     printf("Argument %d is %s.\n", i, argv[i]);
return 0;
}

2、GNU提供的一种高级方法
getopt() 函数位于 unistd.h 系统头文件中。它使得可以以"-a -i"这样的形式来设置不同类型的灵活的命令行参数。


普通函数的可变参数


1、标准提取方法
想要使用可变参数表,那么要求参数表必须至少包括一个有名参数。下面的宏包含在stdarg.h中。

va_list类型:该类型的变量用于依次指向各个无名参数。

void va_start (va_list ap, paramN)宏函数。用于初始化va_list。
参数一:宏执行完之后,ap会指向第一个无名参数。
参数二:最有一个有名参数。

void va_copy (va_list dest, va_list src)宏函数。用于拷贝一份va_list。

type va_arg (va_list ap, type)宏函数,用于取出一个无名参数。
参数一:当前的va_list变量,每执行一次va_arg后,该变量就会后移一个参数。
参数二:指定该变量的数据类型,类型会决定va_list后移的步长。

void va_end (va_list ap)宏函数。用于做一些清理工作。

下面是一个例子:
#include <stdarg.h>
#include <stdio.h>
// this function returns minimum of integer numbers passed.  First
// argument is count of numbers.
int min(int arg_count, ...)
{
  int i;
  int min, a;
   
  // va_list is a type to hold information about variable arguments
  va_list ap;
 
  // va_start must be called before accessing variable argument list
  va_start(ap, arg_count);
    
  // Now arguments can be accessed one by one using va_arg macro
  // Initialize min as first argument in list  
  min = va_arg(ap, int);
    
  // traverse rest of the arguments to find out minimum
  for(i = 2; i <= arg_count; i++) {
    if((a = va_arg(ap, int)) < min)
      min = a;
  }  
 
  //va_end should be executed before the function returns whenever
  // va_start has been previously used in that function
  va_end(ap);  
 
  return min;
}
 
int main()
{
   int count = 5;
    
   // Find minimum of 5 numbers: (12, 67, 6, 7, 100)
   printf("Minimum value is %d", min(count, 12, 67, 6, 7, 100));
   getchar();
   return 0;
}

2、自主获取可变参数
如果对可变参数的个数和栈足够熟悉的话可以自主从栈中读取无名参数。
下面是一个可变长参数的例子,实现多个数的相加。第一个参数是后面参数的个数。

int add(int num, …)
{
     int sum = 0;
     int *p =(int*)&num + 1;
     for(int i=0;i<num;i++)
          sum += *p++;
     return sum;
} 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章