c数组与指针(完)

内容概要

  一、通过指针访问数组元素

  二、指针数组

  三、数组指针

  四、数组指针与二维数组

 

1、通过指针访问数组元素

  -数组存储的是数组第一个元素的地址(但是数组绝不等于第一个元素)

#include <stdio.h>

int main(void){
    int score_a[10];
    int i;
    int *score;
    
    for (i=0; i<10; i++){
        score_a[i] = i;
    }
    
    score = score_a;
    // 等价于socre = &score_a[0];
    
    printf("score_a: %p\n",score_a);
    printf("score: %p\n",score);
    printf("socre_a[1]: %p\n",&score_a[0]);
    
    return 0;
}

 

  -通过指针访问数组元素

#include <stdio.h>

int main(){
    int score_a[10];
    int i;
    int *score;
    
    for (i=0; i<10; i++){
        score_a[i] = i;
        
    }
    
    score = score_a; // score指针指向数组第一个元素
    
    printf("score_a[1]: %d\n", *(score+1)); //访问数组第二个元素
    printf("socre_a[2]: %d\n", *(score+2)); //访问数组第三个元素
    
    return 0;
}

  *score是访问score存储的内存地址对应的变量下存储的值

  *(score+1)是访问score存储的内存地址对应的下一个地址对对应存储的值

  *(score+n)是访问score存储的内存地址对应的下n个地址对应的存储的值

 

  -一个计算字符串长度的小功能

    通过指针的方式

#include <stdio.h>

int main(){
    char str[] = "hello world";
    char *pa;
    int count = 0;
    
    for (pa=str; *pa++ != '\0';){
        count++;
    }
    printf("%d\n",count);
    
    return 0;
}

 

  不要使用字符指针存储字符串,比如

char *pstr = "hello world";

  字符串还是要有真正的存放空间的,如果字符指针改变了,那么这个字符串常量就不可能被访问了,除非你使用const关键字把指针变量不可变

#include <stdio.h>

int main(void){
    const char * const pstr = "hello world";
    const char *pstr1 = "enmmmm....";
    char *pstr2 = "hahahah";  // 只有这个会有警告
    return 0;
}

 

2、指针数组

  指针数组的每个元素的类型都是一种指针类型

#include <stdio.h>

int main(){
    char *pa[6];  //定义了一个指针数组
    char str_array[6] = "hello";
    for (int i = 0;i < 6;i++){
        pa[i] = &str_array[i];  //给数组中每一个指针元素关联指针
    }
    
    for (int j = 0;j < 6;j++){
        printf("%p\n",pa[j]);  //遍历指针数组中的每一个指针
    }
    return 0;
}

  指针数组通常用于存储字符串的数组(这种数组的类型为char *类型)

#include <stdio.h>

int main(){
    char *phrase[] = {
        "hello world",
        "you can you up no can no bb",
        "can can can can?",
        "never give up"
    };
    
    int i;
    
    for (i=0; i<4; i++){
        printf("%s\n",phrase[i]);
    }
    
    return 0;
}

 

  小练习,使用指向指针的指针copy新的数组(有点绕)

#include <stdio.h>

int main(){
    char *phrase[] = {
        "hello world",
        "you can you up no can no bb",
        "can can can can?",
        "never give up"
    };
    
    char **my_phrase = &phrase[2];
    
    char **other_phrase[3];
    
    other_phrase[0] = &phrase[0];
    other_phrase[1] = &phrase[1];
    other_phrase[2] = &phrase[3];
    
    return 0;
}

  ***代画图***

 

3、数组指针

  数组指针的定义

#include <stdio.h>

int main(){
    int (*pa)[4];
    return 0;
}

 

4、数组指针与二维数组

  指针要得到内存地址,还要知道指向的值的使用方法

  -数组指针与二维数组

     对于一维数组,可以使用指针的形式访问数组

#include <stdio.h>

int main(){int array[3] = {1,2,3};
    int *x;
    x = array;
    printf("%d\n",*(array+1));
    printf("%d\n",*(x+1));return 0;
}

    注意:array+1和x+1并不是将内存地址简单的加一,而是告诉编译器跳转到下一个元素的内存地址(在这里每个元素之间的内存地址相差为4,因为是整形)

#include <stdio.h>

int main(){
    int array[2] = {0};
    int *x=&array[0], *y=&array[1];
    
    printf("%d\n",y-x);
    //打印的结果居然不是4,而是1(指的是y的内存地址到x的内存地址相差一个元素的数据长度)
    
    return 0;
}

 

    验证二维数组的地址是第一个子数组的第一个元素的内存地址

#include <stdio.h>

int main(){
    int array[3][4] = {0};
    
    printf("array:%p   &array[0][0]:%p\n",array,&array[0][0]);  //两个地址是一样的
    
    return 0;
}

    尝试通过*(数组+数字)的方式访问数组

#include <stdio.h>

int main(){
    int array[3][4] = {0};
    
    printf("array:%p   &array[0][0]:%p\n",array,&array[0][0]);
    
    printf("array+1:%p   &array[1][0]:%p\n",array+1,&array[1][0]);
    
    //发现array+1的地址与array[1][0]的地址是一样的,并且array+1内存地址与array的内存地址相差16个字节
return 0; }

   -如果像一维数组那样使用指针访问数组元素呢

#include <stdio.h>

int main(){
    int array[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
    int *pa = array;  // 这里就报错了,因为指针虽然拿到了地址,但是它不知道数据之间的跨度是多少(int 告诉指针每个元素之间是4个字节,其实应该是16个)
    
    printf("*p:%d  *(p+1):%d  *(p+2):%d  \n", *pa, *(pa+1), *(p+2));
    
    return 0;
}

 

   -此时使用数组指针,将指针指向一个数组

#include <stdio.h>

int main(){
    int array[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
    int (*pa)[4] = array;  // ()必须加,因为[]的优先级比*高,如果不加(),编译器会将语句识别为指针数组;int [4]告诉编译器pa指向的地址中数据长度为 4*4 = 16字节
    
    printf("*p:%p  *(p+1):%p  *(p+2):%p  \n",*pa,*(pa+1),*(pa+2)); //一次解引用 *pa拿到第一个子数组的地址、*(pa+1)拿到第二个子数组的地址、**(pa+2)拿到第二个子数组的地址
    printf("*p:%d  *(p+1):%d  *(p+2):%d  \n",**pa,**(pa+1),**(pa+2)); //第二次解引用拿到子数组的第一个元素
    
    return 0;
}

  可见,编译器对于数据长度的要求是那么的重要。比如二维数组定义时就初始化时,数组第一个[]号可以不加数字,但是第二个一定需要加入数字(因为只有这样,编译器才能求出每个元素的数据长度)

 

  -自由访问二维数组中每个元素

#include <stdio.h>

int main(){
    int array[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12}; 
    int (*pa)[4] = array;
    
    // printf("(array+1)+2:%d  (array+2)+3:%d \n",((array+1)+2),((array+2)+3));  这是错误的
    
    printf("(array+1)+2:%d  (array+2)+3:%d \n",*(*(array+1)+2),*(*(array+2)+3));
    printf("*(*(pa+1)+2):%d  *(*(pa+2)+3):%d \n",*(*(pa+1)+2), *(*(pa+2)+3));
    
    return 0;
}

***完***

posted @ 2021-03-13 11:59  口乞厂几  阅读(98)  评论(0)    收藏  举报