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;
}
目录
相关文章
|
18天前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
30 3
|
16天前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
37 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
3天前
|
C语言
【c语言】动态内存管理
本文介绍了C语言中的动态内存管理,包括其必要性及相关的四个函数:`malloc`、``calloc``、`realloc`和`free`。`malloc`用于申请内存,`calloc`申请并初始化内存,`realloc`调整内存大小,`free`释放内存。文章还列举了常见的动态内存管理错误,如空指针解引用、越界访问、错误释放等,并提供了示例代码帮助理解。
11 3
|
16天前
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
33 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
|
19天前
|
编译器 程序员 C语言
深入C语言:动态内存管理魔法
深入C语言:动态内存管理魔法
|
24天前
|
存储 程序员 编译器
C语言——动态内存管理与内存操作函数
C语言——动态内存管理与内存操作函数
|
5天前
|
存储 C语言
【c语言】字符串函数和内存函数
本文介绍了C语言中常用的字符串函数和内存函数,包括`strlen`、`strcpy`、`strcat`、`strcmp`、`strstr`、`strncpy`、`strncat`、`strncmp`、`strtok`、`memcpy`、`memmove`和`memset`等函数的使用方法及模拟实现。文章详细讲解了每个函数的功能、参数、返回值,并提供了具体的代码示例,帮助读者更好地理解和掌握这些函数的应用。
9 0
|
14天前
|
C语言
保姆级教学 - C语言 之 动态内存管理
保姆级教学 - C语言 之 动态内存管理
13 0
|
19天前
|
存储 C语言
深入C语言内存:数据在内存中的存储
深入C语言内存:数据在内存中的存储
|
19天前
|
C语言 C++
c语言回顾-内存操作函数
c语言回顾-内存操作函数
38 0