使用参数时为什么使用指针?

时间:2016-11-04 01:31:32

标签: c

有关于*argv[]的问题:

#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <string.h>

int main(int argc, char *argv[])
{
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <string>\n", argv[0]);
        return 1;
    }

    char *input = argv[1];
    for (int i = 0; i < strlen(input); i++) {
        if (isalpha(input[i]) == 0)
            return 1;
    }   

argc对我有意义,因为它是一个int变量,包含随命令传递的参数数量。但是为什么argv[]需要成为指针而不是变量本身?

为参数配置的内存在哪里,是否有限制?是否有潜在的捕获量?使用参数输入而不是fgets?

2 个答案:

答案 0 :(得分:3)

argv是指向char*数组的第一个元素的指针。 C实际上不具有将数组作为参数传递的能力,而是将指针传递给数组的第一个元素。

对于内存,通常,参数实际存储为单个连续的内存块,NUL分隔字符串。 argv引用一个指向每个参数开头的数组,但指针不是独立分配的。如果您使用以下命令调用程序:

foo arg1 arg2 arg3

内存中的实际布局通常是这样的:

"foo\0arg1\0arg2\0arg3\0"
 ^0   ^1    ^2    ^3     

其中插入符号指定argv条目指向的位置:

argv = {&caret0, &caret1, &caret2, &caret3, NULL};

这种方法的优点是最小的分配器开销(它可以作为单个块分配和释放,而不会在对齐或堆跟踪数据上浪费字节)。 argv的累积长度或参数总数(OS /编译器相关)通常有限制;它很大(在我检查过的最新系统中,字符串的总长度限制在128KB左右),但如果在大型文件树上使用宽泛的glob,则可以点击它。

主要障碍是参数长度限制,以及所有数据一次被解析/加载的事实,其中fgets可以通过一次处理一行来使用更少的内存,重用单个(更小) ) 缓冲。但是,如果长度限制不是主要问题,您可以始终使用xargs将输入行的stdin转换为程序的顺序参数。这有点奇怪,但并非不可能。

答案 1 :(得分:2)

  

但是为什么argv []需要成为指针而不是变量本身?

出于同样的原因,您使用指向任何其他函数的指针:避免复制参数或传递数组。 argv需要两者。通过将argv作为char *argv[]传递,只需要复制一个指针而不是可能大量的内存。由于argv是一个数组数组(字符串实际上是指向字节数组的指针),因此没有其他方法可以传递它(有人可能会想出一个复杂的结构)。

因为每次运行程序都会发生,这非常重要。在70年代和80年代开发C和Unix并且计算机的内存和CPU都很少时更为重要。

  

为参数配置的内存在哪里,是否有限制?

参数的内存通常由操作系统或shell分配。在POSIX系统中,通常使用exec family of functions which passes in argv之一调用程序。该限制由操作系统强加。在POSIX中,您可以从ARG_MAX constant in limits.h找到它。

  

使用参数代替fgets是否有潜在的“捕获”?

如上所述,参数的总大小(包括程序名称)有一个限制。在我的Mac上它是262144字节或256K。在Windows 95 it can be as low as 1024 bytes2048 bytes on Win32。生成Makefile时,我遇到了限制as low as 256 bytes in old VMS systemshave had to maintain extensive code to work around these limits(基本上是一堆shell命令)。

另一方面,

fgets仅受文件系统的最大文件大小限制。如果您从STDIN读取,我知道没有限制。