2014-10-05 125 views
3

以下代码示例演示了指针和数组之间的相似性。在第二种方法中,作者将cur_name声明为指向指针的指针。我的问题是,为什么这是必要的?为什么他会声明一个新的指针,而不是仅仅使用原始指针名称?我应该注意到,代码编译并运行良好,当我摆脱cur_name和使用名称,所以这是一个风格而不是功能的问题?任何解释将不胜感激。为什么这个C代码示例使用指针指针?

#include <stdio.h> 

int main(int argc, char *argv[]) 
{ 
    // create two arrays we care about 
    int ages[] = {23, 43, 12, 89, 2}; 
    char *names[] = {"Alan", "Frank", "Mary", "John", "Lisa"}; 

    // safely get the size of ages 
    int count = sizeof(ages)/sizeof(int); 
    int i = 0; 

    // first way using indexing 
    for(i = 0; i < count; i++) { 
     printf("%s has %d years alive.\n", 
       names[i], ages[i]); 
    } 

    printf("---\n"); 

    // setup the pointers to the start of the arrays 
    int *cur_age = ages; 
    char **cur_name = names; 

    // second way using pointers 
    for(i = 0; i < count; i++) { 
     printf("%s is %d years old.\n", 
       *(cur_name+i), *(cur_age+i)); 
    } 

    printf("---\n"); 

    // third way, pointers are just arrays 
    for(i = 0; i < count; i++) { 
     printf("%s is %d years old again.\n", 
       cur_name[i], cur_age[i]); 
    } 

    printf("---\n"); 

    // fourth way with pointers in a stupid complex way 
    for(cur_name = names, cur_age = ages; 
      (cur_age - ages) < count; 
      cur_name++, cur_age++) 
    { 
     printf("%s lived %d years so far.\n", 
       *cur_name, *cur_age); 
    } 

    return 0; 
} 
+0

的代码包含注释' //第三种方式,指针只是数组';这是不准确的 - **指针是_not_数组**。但是,这两者密切相关。考虑'sizeof(cur_name)'和'sizeof(names)'的值;这些值是非常不同的,所以清楚的指针不是数组。请注意'sizeof(argv)'与sizeof(cur_names)'相同;这是因为另一种编写像char * argv []'这样的数组参数的有效方式是'char ** argv'。因此,作为参数传递的数组是指针(这是混淆来自何处),但本地或全局数组不是“只是指针”。 – 2014-10-05 15:39:23

回答

4

该代码使用指向指针的指针来表示指向C字符串数组的指针。即,cur_name是一个指向名为names的C字符串数组的指针。由于C中的字符串本身是由指向char的指针表示的,因此指向此类指针数组的指针变为指向指针的指针。

为什么他会声明一个新的指针而不是仅仅使用原始指针names

因为names不是指针,它是一个指针数组(参见声明之后方括号?这就是使得names的阵列。在前面的单星号是关系到数组元素的类型,这是该程序中的char*)。

形成阵列添加了一个间接的层次:点进的,你需要int*int秒的阵列,但点进的int*数组,你需要一个int**指针。

+0

谢谢你的回复。不过,要澄清一点。如果'names'不是一个指针,那么为什么在第三个方法中'*(names + i)'返回与*(cur_name + i)'相同的值? – intelli78 2014-10-05 22:19:28

+0

@ intelli78这是一个很好的问题!其原因是指针算法的所有规则也适用于数组。这些表达式中数组的名称以与处理数组初始元素的指针相同的方式处理。换句话说,如果你使用'char ** names2 = names',那么它的指针算术表达式就会和'names'上的表达式一样。 – dasblinkenlight 2014-10-05 22:26:04

+0

这很有帮助,谢谢。 – intelli78 2014-10-05 22:32:50

0

作者确实在第四种方法中增加了它们,所以他需要临时对象,但是您在第二种方法中没有必要使用它是正确的。也许他正在使用这个任务来展示他们的等价性?

我认为如果每个方法都在自己的函数中实现,示例会更清晰。

2

如果如果要定义一个指针到它的第一元件具有类型T的数组如下

T a[N]; 

那么你必须写

T *p = a; 

现在代替T代表类型定义为

char *names[] = {"Alan", "Frank", "Mary", "John", "Lisa"}; 

阵列names的元素,你会得到

typedef char * T; 
T names[] = {"Alan", "Frank", "Mary", "John", "Lisa"}; 

所以指针数组的第一个元素看起来像

T *cur_name = names; 

如果你现在会做反向替代你会得到

char * *cur_name = names; 
^^^^^^ 
    T