学习笔记(指针与数组)

指针与数组详解

一维数组与指针:

指向一维数组的指针变量:

数组元素的指针就是数组元素的地址,可以用一个指针变量指向一个数组元素

int main() {
    int a[10] = {2,4,6,8,10,12,14,16,18,20};
    int *p;
    p = &a[0];//把a数组中第一个元素的地址赋值给p指针变量
    int *q;
    q = a;//理解:将a[0]的地址赋给q
    return 0;
}

使用指针访问数组的元素:

如果指针变量p的初值为&a[0],则:

1.p + i和a + i就是数组元素a[i]的地址,或者说,他们指向a数组中序号为i的元素

2.*(p + i)或*(a + i)是p + i或a + i所指的元素的值,即a[i]的值

练习:

//一维数组的指针练习
//数组元素赋值,遍历
//
#include <stdio.h>
int main() {
    int arr[5],i;
    int *p = arr;
    printf("请输入五个数字:");
    for ( i = 0;i < 5;i++) {
        scanf("%d",p + i);
    }
    for (int j = 0;j < 5;j++) {
        printf("%d\n",*(p + j));

    }

    return 0;
}

指针带下标的使用(少用,但要知道):

指向数组元素的指针变量也可以带下标,如p[i].p[i]被处理成*(p +i),如果p是指向一个整形数组的元素a[0],则p[i]代表a[i],但要搞清楚p当前值是什么,比如p指向a[3],则p[2]代表的是a[5]

举例:

#include <stdio.h>
int main() {
    int arr[5] = {1,2,3,4,5};
    int *p = arr;//将arr[0]的值赋值给p变量,输出
    printf("%d\n",*(p+2));//输出的数是多少取决于赋值的首元素是多少
    //下面使用p[i]带角标的用法
    printf("%d\n",p[2]);//输出为3
    //不过尽量少用这种方法,容易写错


    return 0;
}
#include <stdio.h>
int main() {
    int a[5] = {10,20,30,40,50};
    int *p = a;
    //遍历数组
    for (int i = 0;i < 5;i++) {
        printf("%d\n",*(p + i));//或者这里直接用p[i]的格式,但自己可能会写错
    }

    return 0;
}

&数组名的使用:

复习举例:

#include <stdio.h>
int main() {
    int arr[5] = {0};
    int *p = arr;
    printf("%p\n",p);
    printf("%p\n",&p);

    return 0;
}

注意:

printf("%p\n",a);//a表示a[0]的地址
printf("%p\n",&a);//&a表示a这个数组的地址,而a这个数组的地址恰好是a[0]的地址

printf("%p\n",a + 1);//a + 1:表示a[1]元素的地址
printf("%p\n",&a + 1);//&a + 1 表示的是a这个数组后面一个数组的地址

二维数组与指针:

在形式上是二维数组,但在实际存储中还是一维数组

a[0][0]的地址可以用a[0]来表示

a[0][1]的地址可以用a[0]+1来表示

a[0][2]可以用a[0]+2表示,以此类推

a为二维数组名,指向一维数组a[0],相当于&a[0][0]

a+i为二维数组名,指向一维数组a[i],相当于&a[i][0]

举例:

#include <stdio.h>
int main() {
    int arr[][4] = {
        {1,2,3,4},
        {5,6,7,8},
        {9,10,11,12}
    };
    printf("%d\n",arr[0][0]);//1
    printf("%p\n",&arr[0][0]);//获取a[0][0]元素对应的地址
    printf("%p\n",arr[0]);//获取a[0][0]的地址
    printf("%p\n",arr);//获取一维数组 a[0]的地址
    printf("%p",&arr);//获取二维数组arr的地址



    return 0;
}

/*讨论:使用数组名,表示数组中各个相关元素的地址和值
 *前提:
 *&a,二维数组a的地址名
 *a,获取a[0]的地址名
 *a[0] 获取a[0][0]的地址名
 *
 *
 *
 *
 *讨论1:a[0][0]相关的
 *a[0][0]的地址:&a[0][0],a[0],*a
 *a[0][0]的值:a[0][0]  *(a[0]),*(*a))
 *
 *
 *讨论2: a[1]相关的
 *a[1]的地址;&a[1],a+1,
 *
 *讨论3:a[1][0]相关的
 *a[1][0]的地址:&a[1][0],a[1],*(a+1)
 *a[1][0]的值:a[1][0],*(a[1]),*(*(a+1))
 *
 *
 *讨论4:
 *a[1][2]相关的:
 *a[1][2]的地址:&a[1][2],a[1]+2,*(a+1)+2
 *a[1][2]的值:a[1][2],*(a[1]+2),*(*(a+1)+2)
 *
 *
 *
 **/

获取元素值的三种表示方法:

a[i][j]下标法

*(a[i]+j)用一维数组名

*(*(a+i)+j)用二维数组名

使用和指针变量访问::

对于a数组中的任一元素a[i][j]:

地址表示:p+i*N+j

值表示:*(p+i*N+j)或者p[i*N+j]

举例:

#include<stdio.h>
int main() {
    int b[4][3] = {                  //b[M][N]
        {10,20,30},
        {40,50,60},
        {100,110,120}
    };
    int *p = b[0];//p是b[0][0]元素的地址
    //则元素b[1][2]对应的地址,元素为
    printf("%p\n",p + 1*3+2);
    printf("%d",*(p + 1*3+2));


    return 0;
}

举例1:

//二维数组中使用指针变量的操作
//使用指针变量访问二维数组,求二维数组的最大值
#include <stdio.h>
int main() {
    int a[3][4] = {
        {10,20,30,40},
        {50,60,70,80},
        {120,11,100,90}
    };
    //传统方式1:
把首元素的地址赋给指针变量p,并定义首地址为最大值
    int max = a[0][0];
    int i,j;
    通过循环,利用指针变量访问数组中的元素并找出最大值
    for (i =0;i < 3;i++) {
        for (j = 0;j<4;j++) {
            if (a[i][j] > max) {
                max = a[i][j];
            }
        }
    }printf("最大值是:%d\n",max);

//方式二:
    int max = a[0][0];
    int *p = &a[0][0];
    int i,j;
    for (i =0;i < 3;i++) {
            for (j = 0;j<4;j++) {
            if (max < *(p + i*3+j)) {
                max = *(p + i*3+j);
            }
            }
         }
    printf("最大值是:%d\n",max);


   //方式3:使用单个for循环
    int *q,zuidazhi =a[0][0];
    for (q = a[0];q < a[0] + 3*4;q++) {
        if (zuidazhi < *q) {
        zuidazhi = *q;

        }
    }
    printf("zuidahzhi是:%d",zuidazhi);



    return 0;
}

指针数组:

数组指针和指针数组:

数组指针:

当一个指针变量里存放一个数组的首地址时,此指针变量称为指向数组的指针变量,简称数组指针

数组指针是指针

整形指针:int*pint,能够指向整形数据的指针

浮点型指针:float*pf,能够指向浮点型数据的指针

数组指针:能够指向数组的指针

指针数组:

数组是用来存放一系列相同类型的数据,所以也能用来存放指针,这种用来存放指针的数组被称为指针数组,它要求存放在数组中指针的数据类型一致

指针数组是数组

指针数组的使用:

格式:

数据类型 * 指针数组名[大小]

举例:

int *arr[5];

arr是一个数组,有五个元素,每一个元素都是一个整形指针,需用下标来区分。

举例1:

#include <stdio.h>
int main() {
    //如何定义一个指针数组

    int a,b,c,d,e;
    a = 1;
    b = 2;
    c = 3;
    d = 4;
    e = 5;
    int *arr[] = {&a,&b,&c,&d,&e};//定义一个int类型的指针数组
    //通过遍历的方式,取出该数组中每一个值
    for (int i =0;i < 5;i++) {
        printf("%d  ",*arr[i]);
    }


    return 0;
}

举例2:

#include <stdio.h>
int main() {
    int line1[] =  {1,2,3,4};
    int line2[] = {5,6,7,8};
    int line3[] = {9,10,11,12};
    //定义一个指针数组,保存三个一维数组地址
    int *arr[3]= {line1,line2,line3};
    //遍历该数组
    for (int i = 0; i < 3; i++) {  //该循环用来遍历指针数组
        for (int j = 0; j < 4; j++) {  //该循环显示的是内层的,也就是三个一维数组中每个元素的地址
            printf("%d  \n",*(arr[i] + j));
        }
    }

    return 0;
}

字符数组和字符指针变量:

一个字符串,可以用一维字符数组表示,也可以使用字符指针表示

1.字符数组由若干个元素组成,每个元素放一个字符

2.字符指针变量中存放的是地址(字符串/字符数组的首地址),不是将字符串放到字符指针变量中

举例:

#include<stdio.h>
int main() {
    char str[] = {"hello world"};
    char *p = {"hello world"};//把首元素的地址赋值给p这个指针变量
    printf("%p",p);//输出首元素的地址
     printf("%s",p);//输出的是hello world

    return 0;
}

两个方式的区别;

对已声明的字符数组,只能一一对各个元素赋值,不能声明后重新赋值

比如:

char str[14];

str[0] = 'i';//这是对的

str = "hello,world"//这是错的

指针变量是一个变量,可以多次重新赋值

比如:char *pstr = “hell”;

pstr = “hello tom”;//这是对的

一个字符数组,因为他有确定的内存地址,所以字符数组名是一个常量,而定义一个字符指针变量时,它在指向某个确定的字符串数据的情况下,也可以多次赋值

举例:

#include <stdio.h>
int main() {
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    int *p = arr;
    printf("%d\n",p[1]);//2
    printf("%d\n",*(p + 1));//2

    p[1] = 50;
    printf("%d\n",p[1]);//50
    printf("%d\n",arr[1]);//50

    int num = 30;
    p = &num;
    printf("%d\n",*p);//30
    printf("%d\n",p[0]);//30


    return 0;
}
char arr[6] ="hello";
arr[1] = 'm';//错误,已经声明数组中的元素不可以再更改

字符串数组的表示

字符串可以用一维字符数组或字符指针变量两种方式表示。

如果一个数组的每个成员都是一个字符串,则构成了字符串数组,字符串数组有两种表达方式:

1,二维字符数组。

2,字符指针数组

方式1:使用二维字符数组

char fruit[][7] = {
    "apple", "banana", "orange", "grape", "peach", "pear"
};

char weekdays[7][10] ={
    "Monday"
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday",
    "Sunday"
};

字符串数组,一共包含7个字符串,所以第一维的长度是7,其中,最长的字符串长度是10(还有一个

\0占位符),所以第二维的长度同意设为10

方式2:使用字符指针数组表示字符串数组

举例;

int    main() {
    char *weekdays[7] ={
        "Monday"
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday",
        "Saturday",
        "Sunday"
    };

这个字符串数组,其实是一个一维数组,成员就是7个字符指针,每个指针指向一个字符串

练习:

#include <stdio.h>
int main() {
    char *arr[4] = {"三国演义"
        ,"红楼梦",
        "水浒传",
        "西游记"};
    for (int i = 0; i < 4; i++) {
        printf("%s  ",arr[i]);
    }

    return 0;
}

拓展:指向固定长度数组的指针变量

定义一个整形指针变量指向一维数组,一维数组的每个元素包含m个元素

定义格式:

(*标识符)[一维数组元素个数];

例如:

定义一个指针变量p,它指向包含4个元素的一维数组

int(*p)[4];

说明:p先和*结合,说明p是一个指针变量,指向一个大小为4的整形数组

注意:此时定义的是一个指针变量,并非是一个指针数组。(*p必须放在括弧内,否则就成了定义指针数组)

举例:

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值