C语言基础学习第六天,指针与数组

1.段错误

        当我们将代码运行的时候,会看到“段错误”这三个字,令我们很是头疼,因为没有明确标出哪里错了,所以我们盘点一下段错误的几个类型。

1.1 野指针

        1. 定义指针之后,没有将它指向明确的地址。

int *p;
scanf("%d",p);

        2. 指针p被free(释放 )之后,没有置NULL,会让人以为p是合法指针,然后拿它来用

                解决方法:p = NULL

 1.2 内存泄漏,非法空间使用

int *p = (int *)malloc(sizeof(100));
p = (int *)malloc(sizeof(200));

例如,我们先让指针p指向一块地址空间,然后让它指向另外一块,此时,第一次开辟的空间虽然存在,但是我们已经失去了他的地址,没有及时释放,就成为了垃圾内存,会占用资源

 2. 二级指针

一级指针:存储变量的地址

二级指针:存储一级指针的地址

格式:存储类型 数据类型 **指针变量;

int **p; 

 3. 指针与数组

 对于数组的访问:

1. 直接访问:按变量的地址存取变量的值(通过数组名访问)

2. 间接访问:通过存放变量地址的变量去访问变量(通过指针访问)

        前言小提示:在数组中,数组名表示的是首地址,指针记录的也是地址,他们有什么关系呢,或者说,可不可以用指针替换数组名呢,我们接下来看看。

 3.1 指针与一维数组

        直接访问: int a[3] = {1,2,3};

地址元素
a&a[0]1a[0]*a
a+1&a[1]2a[1]*(a+1)
a+2&a[2]3a[2]*(a+2)

        间接访问:int *p = a;

地址元素
p&p[0]1p[0]*p
p+1&p[1]2p[1]*(p+1)
p+2&p[2]3p[2]*(p+2)

         通过两个表格,我们可以看到,他们的格式都是一样的,只不过就是数组名和指针的区别,所以,我们就可以直接用指针替换数组名。

注意:a和p本质不同 a:地址常量 p:变量 a++不可以 p++可以

访问数组的元素a[i]的值:直接:a[i] *(a+i)

                                        间接:p[i] *(p+i)

访问数组的元素a[i]的地址:直接:&a[i] a+i

                                             间接:&p[i] p+i

  3.2 指针与二维数组

        我们之前学习了二维数组的地址,他的数组名+1是指向了第二行,而不是第一行第二个元素,那么,我们怎么要才能让他指向其他列的元素呢?

        在二维数组中,我们可以通过‘ * ’来降级,也就是说,第一行的地址,变成了第一行第一列的地址,这样,在数组名+1的时候,就不是指向第二行的地址,而是第一行第二列的地址。

a:第一行的首地址
*a:第一行第一列的首地址
第一行第二列的首地址:(*a)+1

直接访问:int arr[2][2] = {1,2,3,4};

地址元素
a[0]a / *a&a[0][0]1a[0][0]**a*a[0]
a[0]+1*a+1&a[0][1]2a[0][1]*(*a+1)*(a[0]+1)
a[1]a+1/ *(a+1)&a[1][0]3a[1][0]*(*(a+1))*a[1]
a[1]+1*(a+1)+1&a[1][1]4a[1][1]*(*(a+1)+1)*(a[1]+1)

间接访问: 在这里,我们要学习一个 数组指针,也就是行指针

定义:本质是指针 指向数组(行指针)

格式:存储类型 数据类型 (*指针变量) [列数]

int a[2][3]={1,2,4,4,5,6};

int (*p)[3]=a;

a+1 p+1:移动一整行 移动三个数据单位

        我们可以看到,p与a的作用是一样的,同样是行地址,根据3.1我们学到的,我们是不是直接可以将他们进行替换

地址元素
p[0]p / *p&p[0][0]1p[0][0]**p*p[0]
p[0]+1*p+1&p[0][1]2p[0][1]*(*p+1)*(p[0]+1)
p[1]p+1/ *(p+1)&p[1][0]3p[1][0]*(*(p+1))*p[1]
p[1]+1*(p+1)+1&p[1][1]4p[1][1]*(*(p+1)+1)*(p[1]+1)

访问a[i][j]的值:直接:a[i][j] *(*(a+i)+j) *(a[i]+j)

                           间接:p[i][j] *(*(p+i)+j) *(p[i]+j)

访问a[i][j]的地址:直接:&a[i][j] *(a+i)+j a[i]+j

                              间接:&p[i][j] *(p+i)+j p[i]+j

 3.3 指针数组

        定义:本质是数组,数组中存放的都是指针

        定义格式:存储类型 数据类型 * 指针变量名 [元素的个数];

        int *p[3];

        这个数组中,存放的元素是指针,当我们用数组名来表示的时候,相当于用二级指针去指向,所以,我们只要学会二级指针,指针,普通变量之间的关系,这个指针数组就比较简单了。

**q-->*p-->a,这是他们的指向,接下来我们用几个等式来看看:

1. q = &p;               2. *q = p;          3. p = &a;          4. *p = a;

将3代入到2中,*q = &a

到这里,我们不难看出,再+‘*’,就可以用二级指针q取到a的值

**q = a;

今天的学习就到这里啦,继续努力呀! 

今天留一个小练习,比较简单

已知字符数组a[10]和b[10]中元素的值递增有序,用指针实现将两个数组中元素按照递增顺序输出。

如:char a[10]=”acdgjmno” ; char b[10]=”befhil”;->”abcdefghijlmno”

#include<stdio.h>
int main(int argc, char const *argv[])
{
    char a[20],b[20];//a=acdgjmno;b=befhil;
    gets(a);        //在终端输入两个字符串
    gets(b);        
    char *p = a;
    char *q = b;
    while (*p != '\0' && *q != '\0')//两个字符串都不等于结束符的时候进行循环
    {
        if(*p > *q)         // 比较大小,将小的进行输出,并将指针向后移
        {
            printf("%c",*q);
            q++;
        }
        else
        {
            printf("%c",*p);
            p++;
        }
    }
    if(*p == '\0')//在结束循环时,肯定有一个字符串到结束符了,另一个则没有,那么直接进行输出
        puts(q);
    if(*q == '\0')
        puts(p);
    return 0;
}

 欢迎大家指正!!!!

  • 18
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值