C语言单元小结(4)

本文详细介绍了C语言中的指针概念,包括定义、初始化、运算及野指针的处理。此外,还讲解了const关键字的作用,malloc函数的堆内存管理,以及typedef的类型别名定义。最后,提到了二维数组的特性,并通过实例展示了如何利用指针实现数组的交换和排序功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

指针

1. 定义一个指针变量p,类型是int* ,指向一个int型的数据
int *p
涉及的指针符号:* &
p = &a;//指针的绑定
*p = 23;//指针的解引用,*p得到了变量(a)

2. 定义指针的同时并且初始化
int *p1 = &a; // == int *p, a; p = &a

3. 指针的运算,就是加减指针所指向的变量类型所占字节大小

同一数组中,两指针相减可得出元素的个数。如果是两个数组的指针相减,将导致未定义的结果

    int arr[5] = {1, 3, 5, 7, 9};
    int *p = arr;
    int *q = arr+5;//指向9的后一位
    int ret=q-p;//元素个数

4.野指针
int *p;
危害:1、直接指向内核区 2、指向可用也没有别的数据的区域 3、可用但有别的数据
//NULL专用于指针的初始化(写0)
int *p = NULL;

6.指针与函数值传递

void fun(int *p)//可以不需要返回值
{
    *p=1;//直接修改main中变量
}

int main(void)
{
    int a=0;
    fun(&a);//传入地址
return 0;
}

7.数组指针与函数传递

#include<stdio.h>


int func(int *p,int lenth)//传入数组元素个数,保证函数接口明确,可以正确调用
{
    ...
}

int main(void)
{
    int arr[3]={1,2,3};
    func(arr,3);//数组名作为指针传递
}

8.数组内的指针与解引用

#include<stdio.h>

int main(void)
{

//知识点
//1.*与++有相同的优先级
//2.++后置表示,先传递当前值,完成运算之后再++

     int arr[]={1,3,5,7,9};
     int *p=arr;

        *p++;   //*p、p++
        *(p++); //p的值给*,p++
        //以上两者相同

        (*p)++; //*p、*p整体++,即数值++

        *++p;
        *(++p);//两者相同
#include<stdio.h>

int main(void)
{
//3.printf由右向左入值

     int arr[]={1,3,5,7,9};
     int *p=arr;

    printf("(*p)++ = %d *p = %d.\n", (*p)++, *p);
    //输出11
    printf("*p = %d (*p)++ = %d.\n", *p, (*p)++);
    //将输出12
} 

9.指针数组

    int arr[5] = {1, 2, 3, 4, 5}, i = 0;
    //指针数组,是一个数组,里面的元素是指针
    int *p_arr[5];

//  p_arr[0] = arr;//指针数组第一个元素存储数组首元素首地址
//  p_arr[1] = arr + 1;//指针数组第二个元素存储数组第二个元素地址

    //可以写成for循环
    for (i=0; i<5; i++)
    {
        p_arr[i] = arr + i;
    }   

    printf("*p_arr[2] = %d.\n", *p_arr[2]);

9.函数指针
定义一个函数指针, 并且绑定, C语言里对于函数名的绑定有两种方式:
func、&func,通常写成func

void (*p)(void) = &func或func;

调用函数, 指针的解引用

p 、( )或(*p)( )

10.数组指针与普通数组的绑定与解引用

#include <stdio.h>
int main(void)
{
    int a[3] = {1,3,5};
    int(*p)[3] = a;

    //普通数组
    printf("sizeof(a)=%d\n", sizeof(a));//12
    printf("a=%d\n", a);//a
    printf("a+1=%d\n\n",a + 1);//a+4

    printf("sizeof(&a)=%d\n", sizeof(&a));//4
    printf("&a=%d\n", &a);//a
    printf("&a+1=%d\n\n", (&a) + 1);//a+12

    //数组指针
    printf("sizeof(*p)=%d\n", sizeof(*p));//12
    printf("(*p)=%d\n", *p);//9436216
    printf("(*p)+1=%d\n\n", (*p) + 1);//9436220

    printf("sizeof(p)=%d\n", sizeof(p));//12
    printf("p=%d\n", (p));//a
    printf("p+1=%d\n\n", (p + 1));//a+12

    printf("sizeof(*(*p)=%d\n", sizeof(*(*p)));//4
    printf("*(*p)=%d\n", (*(1=%d\n\n", (*(*p))

可以看出,数组指针中的*p相当于普通数组中的数组名a,p相当于普通数组中的&a

这里写图片描述


const

const 关键字, 修饰的变量是常数,不可更改。只能初始化一次。
const修饰一个普通变量

#include<stdio.h>

int main(void)
{
        const int a=0;//const修饰a,只能初始化一次

        a=3;//错误,不可以直接通过a修改内容

        int *p=NULL;
        p=&a;
        *p=2;//正确,可以通过指针更改内容
        printf("%d",a);

        return 0;
}  

const修饰一个指针类型变量

        const int *p;//const修饰*p,p的内容不可更改
        int const *p;//同上

        int * const p;//const修饰p,p本身不可修改

        const int *const p;//const修饰p本身及其内容,均不可改

malloc

堆内存也是内存的一种,需要程序员自己手动申请malloc,手动释放
编译器不会自动回收,申请的内存伴随整个程序

流程:申请,判断成功,初始化,使用,释放,指针设置为空

注意:malloc申请的空间,默认是有最小分配的

If size is 0, then malloc() returns either NULL, or a unique pointer
value that can later be successfully passed to free().
如果长度为0,则返回不是空指针,而是一个可以被成功返回的唯一指针。


typedef

1.typedef int my_int//将int重命名为my_int
2.typedef char * my_char//将char*重命名为my_char
3.typedef (void (*p)(void)) my_func//将void * void 类型的函数重命名为my_func
4.typedef void (*p_arr[10])(void);//函数指针数组:数组里面的元素都是指针(函数指针)


二维数组

二维数组的变量名是首元素首地址{arr[0], arr[1]}

int arr[2][3] = {1, 2, 3, 4, 5, 6};
arr代表数组首元素首地址(&arr[0])

&arr[0]代表第一维数组的首元素首地址
&arr[0][0]代表数组的第二维数组是首元素首地址

    int arr[2][3] = {1, 2, 3, 4, 5, 6}; 
    int (*p)[3];//数组指针, 指针指向了一个int[3]类型的数据结构
    p = arr;

    //指针方式遍历二维数组
    int i = 0, j = 0;

    for (i=0; i<2; i++)
    {
        for (j=0; j<3; j++)
        printf("*(*(p+%d)+%d) = %d.\n", i, j, *(*(p+i)+j));
    }
实现:

利用传值调用实现swap功能
这里写图片描述

利用malloc申请动态数组,完成排序
这里写图片描述
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值