* []和**之间的C差异

时间:2010-11-17 19:42:47

标签: c arrays pointers

这可能是一个基本问题,但写char * []和char **有什么区别?例如,在main中,我可以有一个char * argv []。或者我可以使用char ** argv。我假设两种符号之间必须存在某种差异。

8 个答案:

答案 0 :(得分:20)

在这种情况下,根本没有区别。如果您尝试使用数组类型作为函数参数,编译器会将其“调整”为指针类型(即,T a[x] 作为函数参数表示完全< / em>与T *a)相同。

在正确的情况下(例如,作为函数参数),使用数组和指针表示法之间可能存在差异。一个常见的是extern声明。例如,假设我们有一个包含以下内容的文件:

char a[20];

我们想让它在另一个文件中可见。这将有效:

extern char a[];

但这不会:

extern char *a;

如果我们改为使用指针数组:

char *a[20];

...同样仍然如此 - 声明一个extern数组工作正常,但声明一个extern指针不会:

extern char *a[]; // works

extern char **a;   // doesn't work

答案 1 :(得分:9)

取决于具体情况。

作为一个函数参数,它们对于编译器来说意味着相同的东西,但是编写它char *argv[]可能有助于使程序员明白传递的char**指向一个元素的第一个元素。数组char*

作为变量声明,它们意味着不同的东西。一个是指针指针,另一个是指针数组,数组大小不明确。所以你可以做:

char * foo[] = {0, 0, 0};

获取一个包含3个空指针的数组。三个char*与指向char*的指针完全不同。

答案 2 :(得分:4)

您可以使用cdecl.org将其转换为英语:

  • char *argv[] =将argv声明为char的指针数组

  • char **argv =将argv声明为指向char的指针

答案 3 :(得分:2)

我认为这比语法糖更多一点,它还提供了一种表达每种声明所隐含的(自愿)合同的语义信息的方法。

对于char*[],您说这是用作数组。

使用char**,你说你可以将它用作数组,但这不是它的用途。

答案 4 :(得分:2)

确实取决于声明发生位置的上下文。

在函数参数定义之外,声明

T a[];

a声明为未知大小的T数组;数组类型不完整,因此,除非a 定义在其他地方(在此翻译单元或另一个链接的翻译单元中),否则不会留出任何存储空间对于它(如果你试图链接,你将可能得到一个“未定义的引用”错误,虽然我认为gcc的默认行为是用1个元素定义数组)。它不能用作sizeof运算符的操作数。 可以用作&运算符的操作数。

例如:

/** 
 * module1.c
 */
extern char *a[]; /* non-defining declaration of a */

void foo()
{
  size_t i = 0;
  for (i = 0; a[i] != NULL; i++)
    printf("a[%lu] = %s\n", (unsigned long) i, a[i++]);
}

module1.c使用a非定义声明来引入名称,以便可以在函数foo中使用它,但由于没有指定大小,在此翻译单元中没有为其预留存储空间。最重要的是,表达式a 不是指针类型;它是一个不完整的数组类型。它将在通常规则的printf调用中转换为指针类型。

/**
 * module2.c
 */
char *a[] = {"foo", "bar", "bletch", "blurga", NULL}; /* defining declaration of a */

int main(void)
{
  void foo();

  foo();
  return 0;
}

module2.c包含a定义声明(数组的大小是根据初始化程序中的元素数计算的),这会导致为数组分配存储空间。

样式说明:请不要写这样的代码。

在函数参数声明的上下文中,T a[]T *a同义;在这两种情况下,a都是指针类型。在函数参数声明的上下文中,这只是 true。

答案 5 :(得分:1)

保罗在上面的评论中说,这是语法糖。 char *和char []都是相同的数据类型。在内存中,它们都包含char的地址。

数组/索引表示法在声明和访问中等效于指针表示法,但有时更直观。如果要创建一个char指针数组,您可能希望以某种方式编写它以阐明您的意图。

编辑:没有考虑杰瑞在另一个答案中提到的案例。看一看。

答案 6 :(得分:1)

正如在其他答案中提到的那样,char*[]声明了一个指向char的指针数组,char**声明了一个指向char的指针(可以用作数组)。

一个区别是数组是常量,而指针不是。

示例:

int main()
{
    char** ppc = NULL;
    char* apc[] = {NULL};
    ppc++;
    apc++; /* this won't compile*/
    return 0;
}

答案 7 :(得分:1)

    char *ptr[2]={"good","bad"}; //Array of ptr to char
    char **str;  //Refer ptr to ptr to char
    int i;
    //str = &ptr[0];  //work
    str = ptr;

    for(i=0;i<2;i++)  printf("%s %s\n",ptr[i],str[i]);

它的o / p相同。使用它我们可以很容易地理解。