指针和数组之间的详细区别

时间:2017-05-31 03:03:29

标签: c arrays pointers

以下是C:

中的代码
void test1(void);

int main(){
    test1();
    return 0;
}

void test1(void){
    char c,
        *p = &c,
        *sp1[3] = {"this 1","this 2", "this 3"},    //pointers array
        (*sp2)[5] = {"this 1","this 2", "this 3"},  
        //2 dimensions array declaration in method 1 
        sp3[][5] = {"this 1","this 2", "this 3"};   
        //2 dimensions array declaration in method 2

    p++;    //ok 
    sp1++;  //error 
    sp2++;  //ok
    sp3++;  //error     
}

我读过一个指针是一个变量,所以增量是可以的,但数组名不是一个变量,所以赋值是不可接受的。

在上面的代码中,p是一个指针,所以增量是正确的; sp1sp3都是数组名称,增量会导致错误,但为什么sp2可以呢?

在同一本书中,有如下功能:

//print lines 
void writelines(char *lineptr[],int nlines){
    while(--nlines >= 0){
        printf("%s\n",*lineptr++);
    }
}

在此函数中,lineptr是数组的名称,但会对其应用增量。为什么?是因为参数是用C中的值转换的,所以lineptr实际上是指针吗?

1 个答案:

答案 0 :(得分:2)

目前还不清楚你的代码试图完成什么,而不仅仅是与指针和数组搏斗,试图围绕它们的使用(这是你的C学习时间的极好用途)。

考虑到这一点,让我们看看你的声明,并试着帮助理解它们。首先让我们看看cp(我已经初步化了'c'以避免使用未初始化的值):

    char c = 'a',
        *p = &c,

c简单地声明为char,在函数堆栈上创建1-char自动存储。 p被声明为字符指针(或指向char 的指针),其值初始化为地址 c

(指针只是一个变量,用于保存其他内容的地址作为其值。正常变量,例如c包含立即值,在这种情况下为'a'。{{1}只需将p的地址作为其值,例如c指向p

接下来声明一个指针数组,它们被初始化为保存初始化程序中提供的字符串文字的地址,例如

c

注意:如果要提供每个指针的初始化,则无需指定 *sp1[] = {"this 1","this 2", "this 3"},

在这里,您有效地将3 的数组声明为char * 3-pointers指向sp1[0]"this 1"指向sp1[1]等等......

接下来,你声明一个指向数组5 char 的指针(或指向5-chars数组的指针)注意:,就像在我的评论中那样,是不够的2 -chars,因此它被声明为指向下面"this 2"数组的指针。现在,您需要注意这里。由于您声明了一个指向数组的指针,它本身没有为7个字符分配任何存储空间(它只是一个指向已存在7个字符的指针)。你有几个选择。

由于7-chars的类型为sp3,您可以在char[][7]之后声明sp2,并为其指定兼容数组的地址,例如

sp3

*sp1[] = {"this 1","this 2", "this 3"}, sp3[][7] = {"this 1","this 2", "this 3"}, (*sp2)[7] = sp3, 指向sp2的开头,或者您可以使用C99 复合文字sp3声明后的文字创建存储空间,例如

sp2

最后,您可以为 *sp1[] = {"this 1","this 2", "this 3"}, /* using a compound literal to create storage */ (*sp2)[7] = (char [][7]){"this 1","this 2", "this 3"}, sp3[][7] = {"this 1","this 2", "this 3"}, 动态分配存储空间(我们将再次离开)。现在因为你只是在这里与指针搏斗,你看到你不能简单地增量 sp2它是一个数组,但是......你可以声明一个指针指向它的开头并将其作为一部分递增你的运动,例如

sp3

现在将拼图的所有部分组合在一起并执行每个指针的增量,您可以执行类似于以下操作的操作。 (注意:我在递增 sp3[][7] = {"this 1","this 2", "this 3"}, *p3 = *sp3; /* pointer to first element in sp3 */ 之后不会降低p的价值,而是我还是p++,因此它仍然指向有效的存储空间)

p - 1

示例使用/输出

#include <stdio.h>

void test1 (void);

int main (void) {
    test1();
    return 0;
}

void test1 (void) {
    char c = 'a',
        *p = &c,
        *sp1[] = {"this 1","this 2", "this 3"},
        /* using a compound literal to create storage */
        (*sp2)[7] = (char [][7]){"this 1","this 2", "this 3"},  
        sp3[][7] = {"this 1","this 2", "this 3"},
        *p3 = *sp3; /* pointer to first element in sp3 */

    p++;        /* advance p to one-char-past-c     */
    (*sp1)++;   /* advance pointer to sp1[0] by one */
    sp2++;      /* advance pointer to next char[7]  */
    p3++;       /* advance pointer to sp3[0] by one */

    printf ("(p - 1): %c\n*sp1: %s\n*sp2: %s\np3  : %s\n",
            *(p - 1), *sp1, *sp2, p3);
}

注意:如果您选择在$ ./bin/arrayptrinc (p - 1): a *sp1: his 1 *sp2: this 2 p3 : his 1 之后声明sp2并让sp3指向sp2的开头,则输出相同用:

sp3

虽然我不确定这是否与您的想法完全相同,但我认为它与您锻炼身体的位置非常接近。如果没有,请告诉我。仔细看看,如果您有任何其他问题,请告诉我。