简体   繁体   English

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

[英]Detailed difference between pointer and array

Below is the code in C: 下面是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     
}

I've read that a pointer is a variable, so increment is ok for it, but an array name is not a variable, so assignment is not acceptable. 我读过一个指针是一个变量,因此可以增加它的值,但是数组名称不是变量,因此赋值是不可接受的。

In the code above, p is a pointer, so an increment is right; 在上面的代码中, p是一个指针,因此增量是正确的; sp1 , sp3 are both array names and increment causes errors, but why is it ok for sp2 ? sp1sp3都是数组名,增量会导致错误,但是为什么sp2呢?

In the same book, there is a function as below: 在同一本书中,具有以下功能:

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

In this function lineptr is the name of an array, but an increment is applied on it. 在此函数中, lineptr是数组的名称,但是会对其施加增量。 Why? 为什么? Is it because the parameter is converted by value in C, so lineptr is actually a pointer? 是否因为参数是通过C中的值转换的,所以lineptr实际上是一个指针?

It is unclear what you code is attempting to accomplish other than simply wrestling with pointers and arrays to try and wrap your head around their use (which is an excellent use of your C learning time). 除了简单地与指针和数组进行搏斗以尝试绕过它们的使用(这是对C语言学习时间的一种很好的利用)之外,尚不清楚您的代码正在尝试完成什么。

With that in mind, let's look at your declarations and try and help make sense out of them. 考虑到这一点,让我们看看您的声明,并尝试使它们变得有意义。 First let's look at c and p (I have initialized 'c' for you to avoid working with an uninitialized value): 首先让我们看一下cp (为避免使用未初始化的值,我已经为您初始化了'c'):

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

c is simply declared as a char with automatic storage for 1-char created on the function stack. 简单地将c声明为char并为在函数堆栈上创建的1-char自动存储。 p is declared as a character pointer (or pointer to char ) and its value is initialized to the address of c p被声明为字符指针(或指向char的指针 ),其值初始化为c地址

(a pointer is simply a variable that holds the address of something else as its value. a normal variable, eg c holds an immediate-value, 'a' in this case. p simply holds the address of c as its value, eg p points to c ) (指针只是一个变量,将其他内容的地址保留为其值。普通变量,例如c保留一个立即值,在这种情况下'a' p只是将c的地址保留为其值,例如p指向c

You next declare an array of pointers that are initialized to hold the addresses of the string literals provided in the initializer , eg 接下来,您声明被初始化为保持在初始提供的字符串文字的地址指针数组 ,如

        *sp1[] = {"this 1","this 2", "this 3"},

note: you do not need to specify 3 if you are providing initialization of each of the pointers. 注意:如果要提供每个指针的初始化,则无需指定3

Here you effectively declare an array of 3-pointers to char * . 在这里,您有效地向char *声明了一个3-pointers数组。 Where sp1[0] points to "this 1" , sp1[1] points to "this 2" , etc... 其中sp1[0]指向"this 1"sp1[1]指向"this 2"sp1[1]

Next you declare a pointer to an array 5 char (or pointer to an array of 5-chars) Note: as in my comment, that is insufficient by 2-chars, so it is declared as a pointer to an array of 7-chars below. 接下来,您声明一个指向5个字符的数组的指针(或指向一个5个字符的数组的指针) 注意:如我的评论所述,不足2个字符,因此将其声明为指向7-chars的数组的指针下面。 Now here is where you need to take care. 现在,这里是您需要保重的地方。 Since you declare a pointer to an array it itself does not have any storage allocated for 7-chars, (it is just a pointer to something that already holds 7-chars). 因为您声明了一个指向数组指针,所以它本身没有为7个字符分配任何存储空间(它只是一个指向已经包含7个字符的指针的指针)。 You have a few options. 您有几种选择。

Since sp3 is of type char[][7] , you can declare sp2 after sp3 and assign it the address of a compatible array, eg 由于sp3的类型为char[][7] ,因此可以在sp3之后声明sp2并为其分配兼容数组的地址,例如

    *sp1[] = {"this 1","this 2", "this 3"},
    sp3[][7] = {"this 1","this 2", "this 3"},
    (*sp2)[7] = sp3,  

to have sp2 point to the beginning of sp3 , or you can create storage for the literals following your sp2 declaration by using the C99 compound literal , eg 使sp2指向sp3的开头,或者您可以使用C99 复合文字 ,在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"},

And finally, you can dynamically allocate storage for sp2 (which we will leave for another time). 最后,您可以为sp2动态分配存储空间(我们将再等待一次)。 Now since you are just wrestling with pointers here, you see you cannot simply increment sp3 it is an array, but... you can declare a pointer to its beginning and increment that as part of your exercise, eg 现在,由于您只是在这里处理指针,您将看到不能简单地将sp3 递增它是一个数组,但是...您可以声明一个指向其开头的指针,并在练习中将其递增,例如

        sp3[][7] = {"this 1","this 2", "this 3"},
        *p3 = *sp3; /* pointer to first element in sp3 */

Now putting all the pieces of the puzzle together and exercising the increment of each of your pointers, you can do something similar to the following. 现在将难题的所有部分放在一起,并练习每个指针的增量,您可以执行以下操作。 ( note: I do not derefernce the value of p after incrementing p++ , instead I derefernce p - 1 so that it still points to valid storage) 注:我不derefernce的数值p增量后p++ ,而不是我derefernce 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);
}

Example Use/Output 使用/输出示例

$ ./bin/arrayptrinc
(p - 1): a
*sp1: his 1
*sp2: this 2
p3  : his 1

Note: the output is the same if you chose to declare sp2 after sp3 and have sp2 point to the beginning of sp3 with: 注意:如果选择在sp3之后声明sp2并使sp2指向sp3的开头,则输出是相同的:

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

While I'm not sure this is exactly what you had in mind, I think it is close to where you were going with your exercise. 尽管我不确定这是否正是您的初衷,但我认为这与您进行运动的地方很接近。 If not, let me know. 如果没有,请告诉我。 Look things over and let me know if you have any further questions. 仔细检查一下,如果您还有其他问题,请与我联系。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM