C 关于*argv[]的指针

C 关于*argv[]的指针,c,pointers,gdb,arguments,main,C,Pointers,Gdb,Arguments,Main,这是我的main.c ...... int main(int argc, char **argv) { init_arg(&argc, &argv); ...... } 这是我的init_arg.c ...... void init_arg(int *argc, char ***argv) { printf("%s\n", *argv[1]); ...... } 我编译它没有错误和警告 我运行它: /a.out包括 它得到分段错误 调试它时,我

这是我的
main.c

......
int main(int argc, char **argv)
{
    init_arg(&argc, &argv);
    ......
}
这是我的
init_arg.c

......
void init_arg(int *argc, char ***argv)
{
    printf("%s\n", *argv[1]);
    ......
}
我编译它没有错误和警告

我运行它:

/a.out包括

它得到分段错误

调试它时,我发现步骤
printf(“%s\n”,*argv[1])

弄错了,这表明:

print*argv[1]

无法访问地址0x300402bfd处的内存


我想知道,如何在
init_arg()
函数中打印
argv[1]

您需要在(*argv)周围添加一对括号来更改求值顺序。按照当前的方式,[1]首先求值,生成一个无效指针,然后该指针被取消引用,从而导致未定义的行为

printf("%s\n", (*argv)[1]);

Argv已经是一个指针。就这样传过去吧:

init_arg(&argc, argv);
void init_arg(int *argc, char **argv) {
    printf("%s\n", argv[1]);
}
init_arg应该如下所示:

init_arg(&argc, argv);
void init_arg(int *argc, char **argv) {
    printf("%s\n", argv[1]);
}

我假设首先传递
&argc
&argv
的原因是,您可以在
init_arg
中更新它们。一般来说,我喜欢这样编写函数:

/*
 * init_arg: do something useful with argc and argv, and update argc and argv
 * before returning so that the caller can do something else useful that's
 * not shared with all the other callers of init_arg().
 * (this comment of course needs updating to describe the useful things)
 */
void init_arg(int *argc0, char ***argv0) {
    int argc = *argc0;
    char **argv = *argv0;
    ... all the operative code goes here, and then ...
    *argc0 = argc;
    *argv0 = argv;
}

当然,这意味着您不能在
init_arg
内提前执行
return
s,因此有一些折衷办法,但使用相同的常规
argc
argv
inside
init_arg

+1进行调试并将其包含在您的帖子中确实容易得多!在GDB中,当代码崩溃时,运行命令bt以查看导致崩溃的堆栈跟踪。阅读处理程序参数的示例C程序代码。这里有一个示例片段,或者,等效地,您可以使用
argv[0][1]
(与键入一样长,但可能可读性稍高)。@torek我会避免使用
argv[0]
代替
(*argv)
,因为传入的是一个“标量”指针(即指向单个数组的指针),而不是指向数组的指针数组
syntax强调了一个概念,即我们正在寻找一个指向标量的指针。显然,你属于那种喜欢保持C所放弃的区别的人。我很同情!在20世纪80年代初,我有一位同事,他喜欢根据方便的情况随时混合指针和数组符号。尤其是他会这样做例如:
time\u t now[1];time(now);…
而不是
time\u t now;time(&now);…
:-)“[…]保持C删除的区别”这是一个常见的误解,主要是由于数组在传递到函数时衰减为指针。您展示的示例是一个很好且完全合法的示例:将一个项的数组视为指针与将指针视为一个项的数组之间有很大区别。我的观点是C语言不提供任何方法(在被调用方中,例如,函数
fn
)要了解某个指针参数
T*p
是否指向单个项(
T var;fn(&var);
),还是指向
N
顺序项中的第一个项(
T var[N];fn(var);
)。它有助于程序员区分它们,但语言本身并不适合您。例如,与Pascal和Go进行比较。这个答案是正确的,但他也可以通过
argc
,而不是
&argc
。大概传递
&argc
&argv
的目的是允许
init_arg
修改它们。您可以这样修改它们。如果错过了早期返回,只需使用goto:)