C语言指针使用及动态分配内存

简介: C语言指针使用及动态分配内存

一、指针


1、二级指针


#include <stdio.h>
int main() {
    int val = 0;
    int *p_val = &val;      //一级指针
    int **pp_val = &p_val;  //二级指针
    **pp_val/*val变量的存储区*/ = 10;
    printf("val是%d\n", val);
    *pp_val/*p_val指针的存储区*/ = NULL;
    printf("p_val是%p\n", p_val);
    return 0;
}
#include <stdio.h>
int main() {
    char ch = 'e';
    char *p_ch = &ch;
    int val = 45;
    int *p_val = &val;
    float fval = 9.4f;
    float *p_fval = &fval;
    void *p_v = NULL;
    p_v = &ch;      //无类型指针实际起到字符类型指针的作用
    printf("%c\n", *(char *)p_v);   //使用无类型指针前先强制类型转换成字符类型指针
    p_v = &p_ch;    //无类型指针实际起到字符类型二级指针的作用
    printf("%c\n", **(char **)p_v/*ch变量存储区*/);
    p_v = &p_val;   //无类型指针实际起到整数类型二级指针的作用
    printf("%d\n", **(int **)p_v/*val变量存储区*/);
    p_v = &p_fval;  //无类型指针实际起到浮点类型二级指针的作用
    printf("%g\n", **(float **)p_v/*fval变量存储区*/);
    return 0;
}


2、数据交换


#include <stdio.h>
void swap(int **pp_val/*指向p_val指针*/, int **pp_val1/*指向p_val1指针*/) {
    int *p_tmp = NULL;
    p_tmp = *pp_val/*p_val*/;
    *pp_val/*p_val*/ = *pp_val1/*p_val1*/;
    *pp_val1/*p_val1*/ = p_tmp;
}
int main() {
    int val = 3, val1 = 7;
    int *p_val = &val, *p_val1 = &val1;
    swap(&p_val, &p_val1);   //语句结束后p_val指针应该指向val1,p_val1指针应该指向val
    printf("val是%d,val1是%d\n", val, val1);
    printf("*p_val是%d,*p_val1是%d\n", *p_val, *p_val1);
    return 0;
}


3、函数指针


#include <stdio.h>
typedef int (*pfunc_t)(int, int);   //给函数指针类型起名字,名字就是pfunc_t
int add(int val, int val1) {
    return val + val1;
}
int sub(int val, int val1) {
    return val - val1;
}
int main() {
    /*int (*p_add)(int, int) = NULL;    //函数指针声明语句
    int (*p_sub)(int, int) = NULL;*/
    pfunc_t p_add = NULL, p_sub = NULL;  //声明函数指针变量
    printf("add是%p\n", add);   //函数名称可以代表函数的地址
    p_add = add;    //p_add指针指向add函数
    p_sub = sub;
    printf("p_add(3, 8)是%d\n", p_add(3, 8));
    printf("p_sub(8, 6)是%d\n", p_sub(8, 6));
    return 0;
}


4、回调函数


#include <stdio.h>
typedef void (*pfunc_t)(int *);  //创建函数指针类型并命名为pfunc_t
void print_cb(int *p_val) {
    printf("%d ", *p_val);
}
void neg_cb(int *p_val) {
    *p_val = 0 - *p_val;
}
void for_each(int *p_val, int size, pfunc_t p_func/*声明函数指针形式参数*/) {
    int num = 0;
    for (num = 0;num <= size - 1;num++) {
        p_func(p_val + num/*数组里下标为num存储区的地址*/);
    }
}
int main() {
    int arr[] = {1, 2, 3, 4, 5};
    for_each(arr, 5, print_cb);  //把数组里所有存储区的内容显示在屏幕上
    printf("\n");
    for_each(arr, 5, neg_cb);    //把数组里每个存储区的内容都变成相反数
    for_each(arr, 5, print_cb);
    printf("\n");
    return 0;
}


二、动态分配内存


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
    int num = 0;
    int *p_val = NULL;
    srand(time(0));
    p_val = (int *)malloc(5 * sizeof(int)); //动态分配5个整数类型存储区并把第一个存储区的地址记录到p_val指针里
    if (p_val) {
        //把动态分配内存当做数组使用
        for (num = 0;num <= 4;num++) {
            *(p_val + num) = rand() % 36 + 1;  //得到一个1到36之间的随机数并记录到动态分配内存里
        }
        for (num = 0;num <= 4;num++) {
            printf("%d ", *(p_val + num));
        }
        printf("\n");
        free(p_val);//释放内存
        p_val = NULL;
    }
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct {
    int row;
    int col;
} pt;
//从键盘得到一个点的位置并把记录点位置的存储区
//地址作为返回值传递给调用函数
pt *read(void) {
    pt *p_pt = (pt *)malloc(sizeof(pt));  //动态分配一个记录点位置的结构体存储区
    if (p_pt) {
        printf("请输入一个点的位置:");
        scanf("%d%d", &(p_pt->row), &(p_pt->col));    //从键盘得到代表点位置的两个整数并记录到动态分配结构体存储区的两个整数类型子存储区里
    }
    return p_pt;   //如果动态分配内存成功就返回首地址,否则返回NULL
}
int main() {
    pt *p_pt = read();
    if (p_pt) {
        printf("点的位置是(%d, %d)\n", p_pt->row, p_pt->col);   //从被调用函数动态分配的内存里获得点的位置并显示
        free(p_pt);
        p_pt = NULL;
    }
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct {
    int row;
    int col;
} pt;
typedef struct {
    pt pt1;
    pt pt2;
} rect;
rect *read(void) {
    rect *p_rect = (rect *)malloc(sizeof(rect));
    if (p_rect) {
        printf("请输入水平长方形的位置:");
        scanf("%d%d%d%d", &(p_rect->pt1.row), &(p_rect->pt1.col), &(p_rect->pt2.row), &(p_rect->pt2.col));
    }
    return p_rect;
}
pt *midpt(const rect *p_rect) {
    pt *p_mid = (pt *)malloc(sizeof(pt));  //动态分配结构体存储区用来存放中心点位置
    if (p_mid) {
        p_mid->row = (p_rect->pt1.row + p_rect->pt2.row) / 2;
        p_mid->col = (p_rect->pt1.col + p_rect->pt2.col) / 2;
    }
    return p_mid;
}
int main() {
    pt *p_mid = NULL;
    rect *p_rect = read();
    if (p_rect) {
        //返回值不是空指针
        p_mid = midpt(p_rect);
        if (p_mid) {
            //分配成功用来记录中心点
            //位置的结构体存储区
            printf("中心点位置是(%d, %d)\n", p_mid->row, p_mid->col);
            free(p_mid);
            p_mid = NULL;
        }
        free(p_rect);
        p_rect = NULL;
    }
    return 0;
}
目录
相关文章
|
2天前
|
Java 程序员 Linux
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
10 0
|
3天前
|
程序员 C语言
C语言内存管理:malloc、calloc、realloc与free函数详解
C语言内存管理:malloc、calloc、realloc与free函数详解
4 0
|
3天前
|
存储 编译器 C语言
C语言的联合体:一种节省内存的数据结构
C语言的联合体:一种节省内存的数据结构
7 0
|
3天前
|
C语言
C语言中的函数指针、指针函数与函数回调
C语言中的函数指针、指针函数与函数回调
6 0
|
3天前
|
存储 C语言
C语言中的多级指针、指针数组与数组指针
C语言中的多级指针、指针数组与数组指针
6 0
|
3天前
|
存储 C语言
C语言数组指针详解与应用
C语言数组指针详解与应用
10 0
|
14天前
|
消息中间件 存储 Kafka
实时计算 Flink版产品使用问题之 从Kafka读取数据,并与两个仅在任务启动时读取一次的维度表进行内连接(inner join)时,如果没有匹配到的数据会被直接丢弃还是会被存储在内存中
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
6天前
|
存储 Java C++
Java虚拟机(JVM)管理内存划分为多个区域:程序计数器记录线程执行位置;虚拟机栈存储线程私有数据
Java虚拟机(JVM)管理内存划分为多个区域:程序计数器记录线程执行位置;虚拟机栈存储线程私有数据,如局部变量和操作数;本地方法栈支持native方法;堆存放所有线程的对象实例,由垃圾回收管理;方法区(在Java 8后变为元空间)存储类信息和常量;运行时常量池是方法区一部分,保存符号引用和常量;直接内存非JVM规范定义,手动管理,通过Buffer类使用。Java 8后,永久代被元空间取代,G1成为默认GC。
18 2
|
10天前
|
存储
数据在内存中的存储(2)
数据在内存中的存储(2)
24 5
|
10天前
|
存储 小程序 编译器
数据在内存中的存储(1)
数据在内存中的存储(1)
27 5