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

C 为什么在使用参数时使用指针?,c,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

对此有疑问
*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;
    }   
#包括
#包括
#包括
#包括
int main(int argc,char*argv[])
{
如果(argc!=2){
fprintf(stderr,“用法:%s\n”,argv[0]);
返回1;
}
char*input=argv[1];
对于(int i=0;i
argc
对我来说很有意义,因为它是一个int变量,包含随命令传递的参数数。但是为什么
argv[]
需要是指针,而不是本身的变量


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

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

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

foo arg1 arg2 arg3
内存中的实际布局通常如下所示:

"foo\0arg1\0arg2\0arg3\0"
 ^0   ^1    ^2    ^3     
插入符号指定了argv
条目指向的位置:

argv = {&caret0, &caret1, &caret2, &caret3, NULL};
这种方法的优点是分配器开销最小(它可以作为单个块分配和释放,而不会在对齐或堆跟踪数据上浪费字节)。通常对
argv
的累积长度或参数总数(取决于操作系统/编译器)有限制;它很大(在最近的系统上,我检查了这个问题,字符串的总长度被限制在128KB左右),但是如果在一个大的文件树上使用一个大的glob,你就可以找到它

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

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

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

由于每次程序运行时都会发生这种情况,这一点非常重要。在70年代和80年代,当C和Unix被开发出来,计算机的内存和CPU都非常少的时候,这一点更为重要

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

参数的内存通常由操作系统或shell分配。在POSIX系统中,您的程序通常使用其中一个参数进行调用。该限制由操作系统施加。在POSIX中,您可以从中找到它

使用输入参数而不是FGET是否存在潜在的“陷阱”

如上所述,参数的总大小(包括程序名)是有限制的。在我的Mac上是262144字节或256K.On和。我在生成Makefiles(基本上是一堆shell命令)时遇到了限制


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

它是指向char的指针数组,指向char的指针是表示字符串的std c方式。*argv%5B%5d当需要存储和传递一个不可预测的字符串数组时e(可变)长度,一个“锯齿状数组”这种方法工作得很好。锯齿数组是通过指针数组实现的。这正是您在本例中看到的。哦,如果参数实际上是sing chars或int,那么它就没有必要了?指针是一个非常有意义的变量。谢谢您的帮助。我一直在试图强迫自己理解为什么要使用它取消引用及其实际操作。感谢您的输入,这真的很有帮助。@ZachGates太好了!这里有一种方法可以考虑它。内存就像一个存储空间,您可以立即访问任何单元。指针就像一张写着“存储单元1234”的便笺。您可以立即到那里翻找。传递值就像说“复制存储单元1234中的所有内容,并将其移动到我的存储单元”指针的缺点是,如果您对存储单元1234进行任何更改,则会影响使用存储单元1234的所有人。当然,这非常简单。