我应该使用 char** argv 还是 char* argv[]?

发布于 2024-07-17 23:53:41 字数 56 浏览 4 评论 0原文

我刚刚学习 C,想知道我应该在我的主要方法中使用其中哪一个。 有什么区别吗? 哪一种比较常见?

I'm just learning C and was wondering which one of these I should use in my main method. Is there any difference? Which one is more common?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

谷夏 2024-07-24 23:53:41

由于您刚刚学习 C,我建议您首先真正尝试理解数组和指针之间的差异,而不是常见事物。

在参数和数组方面,有一些令人困惑的规则,在继续之前应该先弄清楚。 首先,在参数列表中声明的内容被视为特殊。在某些情况下,C 中的函数参数没有意义。这些是

  • 函数作为参数
  • 、数组作为参数

、数组作为参数

。第二个可能还不是很清楚。 但是,当您考虑到数组维度的大小是 C 中类型的一部分(并且未给出维度大小的数组具有不完整类型)时,情况就会变得很清楚。 因此,如果您要创建一个按值获取数组(接收副本)的函数,那么它只能针对一种大小执行此操作! 此外,数组可能会变得很大,而 C 会尝试尽可能快。

在 C 中,由于这些原因,数组值不存在。 如果你想获取数组的值,你得到的是指向该数组第一个元素的指针。 实际上,这里已经有了解决方案。 C 编译器不会预先绘制无效的数组参数,而是将各个参数的类型转换为指针。 请记住这一点,这非常重要。 该参数不是数组,而是指向相应元素类型的指针。

现在,如果您尝试传递一个数组,则传递的是指向数组第一个元素的指针。

游览:函数作为参数

为了完成这个任务,并且我认为这将帮助您更好地理解问题,让我们看看当您尝试将函数作为参数时的情况是什么。 确实,首先它没有任何意义。 参数怎么可以是函数呢? 嗯,我们当然想要在那个地方有一个变量! 因此,当发生这种情况时,编译器所做的就是将函数转换函数指针。 尝试传递一个函数将会传递一个指向该函数的指针。 因此,以下内容是相同的(类似于数组示例):

void f(void g(void));
void f(void (*g)(void));

请注意,需要将 *g 括起来。 否则,它将指定一个返回 void* 的函数,而不是指向返回 void 的函数的指针。

回到数组

现在,我在一开始就说过数组可以有不完整的类型 - 如果您还没有给出大小,就会发生这种情况。 由于我们已经知道数组参数不存在,而是任何数组参数都是指针,因此数组的大小并不重要。 这意味着,编译器将翻译以下所有内容,并且所有内容都是相同的:

int main(int c, char **argv);
int main(int c, char *argv[]);
int main(int c, char *argv[1]);
int main(int c, char *argv[42]);

当然,能够在其中放入任何大小没有多大意义,并且它只是被丢弃。 因此,C99 为这些数字赋予了新的含义,并允许括号之间出现其他内容:

// says: argv is a non-null pointer pointing to at least 5 char*'s
// allows CPU to pre-load some memory. 
int main(int c, char *argv[static 5]);

// says: argv is a constant pointer pointing to a char*
int main(int c, char *argv[const]);

// says the same as the previous one
int main(int c, char ** const argv);

最后两行表示您将无法在函数内更改“argv” - 它已成为常量指针。 但只有少数 C 编译器支持这些 C99 功能。 但这些特征清楚地表明“数组”实际上并不是一个。 这是一个指针。

警告

注意,只有当您将数组作为函数的参数时,我上面所说的才是正确的。 如果您使用本地数组,则数组将不是指针。 它将表现为指针,因为如前所述,当读取数组的值时,数组将转换为指针。 但它不应该与指针混淆。

一个经典的例子如下:

char c[10]; 
char **c = &c; // does not work.

typedef char array[10];
array *pc = &c; // *does* work.

// same without typedef. Parens needed, because [...] has 
// higher precedence than '*'. Analogous to the function example above.
char (*array)[10] = &c;

As you are just learning C, I recommend you to really try to understand the differences between arrays and pointers first instead of the common things.

In the area of parameters and arrays, there are a few confusing rules that should be clear before going on. First, what you declare in a parameter list is treated special. There are such situations where things don't make sense as a function parameter in C. These are

  • Functions as parameters
  • Arrays as parameters

Arrays as parameters

The second maybe is not immediately clear. But it becomes clear when you consider that the size of an array dimension is part of the type in C (and an array whose dimension size isn't given has an incomplete type). So, if you would create a function that takes an array by-value (receives a copy), then it could do so only for one size! In addition, arrays can become large, and C tries to be as fast as possible.

In C, for these reasons, array-values are not existent. If you want to get the value of an array, what you get instead is a pointer to the first element of that array. And herein actually already lies the solution. Instead of drawing an array parameter invalid up-front, a C compiler will transform the type of the respective parameter to be a pointer. Remember this, it's very important. The parameter won't be an array, but instead it will be a pointer to the respective element type.

Now, if you try to pass an array, what is passed instead is a pointer to the arrays' first element.

Excursion: Functions as parameters

For completion, and because I think this will help you better understand the matter, let's look what the state of affairs is when you try to have a function as a parameter. Indeed, first it won't make any sense. How can a parameter be a function? Huh, we want a variable at that place, of course! So what the compiler does when that happens is, again, to transform the function into a function pointer. Trying to pass a function will pass a pointer to that respective function instead. So, the following are the same (analogous to the array example):

void f(void g(void));
void f(void (*g)(void));

Note that parentheses around *g is needed. Otherwise, it would specify a function returning void*, instead of a pointer to a function returning void.

Back to arrays

Now, I said at the beginning that arrays can have an incomplete type - which happens if you don't give a size yet. Since we already figured that an array parameter is not existent but instead any array parameter is a pointer, the array's size doesn't matter. That means, the compiler will translate all of the following, and all are the same thing:

int main(int c, char **argv);
int main(int c, char *argv[]);
int main(int c, char *argv[1]);
int main(int c, char *argv[42]);

Of course, it doesn't make much sense to be able to put any size in it, and it's just thrown away. For that reason, C99 came up with a new meaning for those numbers, and allows other things to appear between the brackets:

// says: argv is a non-null pointer pointing to at least 5 char*'s
// allows CPU to pre-load some memory. 
int main(int c, char *argv[static 5]);

// says: argv is a constant pointer pointing to a char*
int main(int c, char *argv[const]);

// says the same as the previous one
int main(int c, char ** const argv);

The last two lines say that you won't be able to change "argv" within the function - it has become a const pointer. Only few C compilers support those C99 features though. But these features make it clear that the "array" isn't actually one. It's a pointer.

A word of warning

Note that all i said above is true only when you have got an array as a parameter of a function. If you work with local arrays, an array won't be a pointer. It will behave as a pointer, because as explained earlier an array will be converted to a pointer when its value is read. But it should not be confused with pointers.

One classic example is the following:

char c[10]; 
char **c = &c; // does not work.

typedef char array[10];
array *pc = &c; // *does* work.

// same without typedef. Parens needed, because [...] has 
// higher precedence than '*'. Analogous to the function example above.
char (*array)[10] = &c;
情话已封尘 2024-07-24 23:53:41

你可以使用任何一个。 它们是完全等价的。 请参阅 litb 的评论和 他的答案

这实际上取决于您想要如何使用它(并且在任何情况下您都可以使用其中之一):

// echo-with-pointer-arithmetic.c
#include <stdio.h>
int main(int argc, char **argv)
{
  while (--argc > 0)
  {
    printf("%s ", *++argv);
  }
  printf("\n");
  return 0;
}

// echo-without-pointer-arithmetic.c
#include <stdio.h>
int main(int argc, char *argv[])
{
  int i;
  for (i=1; i<argc; i++)
  {
    printf("%s ", argv[i]);
  }
  printf("\n");
  return 0;
}

至于哪个更常见 - 并不重要。 任何有经验的 C 程序员在阅读您的代码时都会认为两者是可以互换的(在正确的条件下)。 就像经验丰富的英语使用者一样轻松地读出“they're”和“they are”。

更重要的是你学会阅读它们并认识到它们有多么相似。 您阅读的代码将多于您编写的代码,并且您需要对两者都同样熟悉。

You could use either. They're completely equivalent. See litb's comments and his answer.

It really depends how you want to use it (and you could use either in any case):

// echo-with-pointer-arithmetic.c
#include <stdio.h>
int main(int argc, char **argv)
{
  while (--argc > 0)
  {
    printf("%s ", *++argv);
  }
  printf("\n");
  return 0;
}

// echo-without-pointer-arithmetic.c
#include <stdio.h>
int main(int argc, char *argv[])
{
  int i;
  for (i=1; i<argc; i++)
  {
    printf("%s ", argv[i]);
  }
  printf("\n");
  return 0;
}

As for which is more common - it doesn't matter. Any experienced C programmer reading your code will see both as interchangeable (under the right conditions). Just like an experienced English speaker reads "they're" and "they are" equally easily.

More important is that you learn to read them and recognize how similar they are. You'll be reading more code than you write, and you'll need to be equally comfortable with both.

冷默言语 2024-07-24 23:53:41

这没有什么区别,但我使用 char *argv[] 因为它显示这是一个固定大小的可变长度字符串数组(通常是 char *) 。

It doesn't make a difference, but I use char *argv[] because it shows that is a fixed size array of variable length strings (which are usually char *).

只是偏爱你 2024-07-24 23:53:41

您可以使用这两种形式中的任何一种,因为在 C 语言中数组和指针在函数参数列表中是可以互换的。 请参阅http://en.wikipedia.org/wiki/C_(programming_language)#数组指针可互换性

You can use either of the two forms, as in C arrays and pointers are interchangeable in function parameter lists. See http://en.wikipedia.org/wiki/C_(programming_language)#Array-pointer_interchangeability.

长梦不多时 2024-07-24 23:53:41

它实际上没有什么区别,但后者更具可读性。 给你的是一个 char 指针数组,就像第二个版本所说的那样。 然而,它可以像第一个版本一样隐式转换为双字符指针。

It doesn't really make a difference, but the latter is more readable. What you are given is an array of char pointers, like the second version says. It can be implicitly converted to a double char pointer like in the first version however.

静赏你的温柔 2024-07-24 23:53:41

您应该将其声明为 char *argv[],因为声明它的所有等效方法有很多,这最接近其直观含义:字符串数组。

you should declare it as char *argv[], because of all the many equivalent ways of declaring it, that comes closest to its intuitive meaning: an array of strings.

一曲爱恨情仇 2024-07-24 23:53:41

char ** → 指向字符指针的指针,char *argv[] 表示字符指针数组。 由于我们可以使用指针而不是数组,因此两者都可以使用。

char ** → pointer to character pointer and char *argv [] means array of character pointers. As we can use pointer instead of an array, both can be used.

茶底世界 2024-07-24 23:53:41

我认为使用任何一种方法而不是另一种方法都没有什么特别的优点——使用与代码的其余部分最一致的约定。

I see no special merit of using either approach instead of the other -- use the convention that is most in line with the rest of your code.

浅忆 2024-07-24 23:53:41

如果您需要变化或动态数量的字符串,则 char** 可能更容易使用。 如果字符串的数量是固定的,那么 char* var[] 将是首选。

If you'll need a varying or dynamic number of strings, char** might be easier to work with. If you're number of string is fixed though, char* var[] would be preferred.

执手闯天涯 2024-07-24 23:53:41

我知道这已经过时了,但是如果您只是学习 C 编程语言并且没有用它做任何主要的事情,请不要使用命令行选项。

如果您不使用命令行参数,则不要使用其中任何一个。 只需将 main 函数声明为 int main()
如果您

  • 希望程序的用户能够将文件拖到您的程序上,以便您可以用它更改程序的结果,或者
  • 想要处理命令行选项(-help, < code>/? 或终端或命令提示符中 程序名称 之后的任何其他内容)

使用对您更有意义的选项。
否则,只需使用int main()
毕竟,如果您最终想要添加命令行选项,您可以稍后轻松地编辑它们。

I know this is outdated, but if you are just learning the C programming language and not doing anything major with it, don't use command-line options.

If you are not using command line arguments, don't use either. Just declare the main function as int main()
If you

  • Want the user of your program to be able to drag a file onto your program so that you can change the outcome of your program with it or
  • Want to handle command-line options(-help, /?, or any other thing that goes after program name in terminal or command prompt)

use whichever makes more sense to you.
Otherwise, just use int main()
After all, if you end up wanting to add command-line options, you can easily edit them in later.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文