c语言精品网站开发的教学,房屋租赁网站开发背景,接单做效果图网站,网站网址查询ip目录
函数指针#xff1a; 指针函数#xff1a;
参数为指针的函数#xff1a;
参数为数组的函数#xff1a;
C语言内存管理 stdlib.h头文件常用函数介绍
1、局部变量 2、全局变量
3、 堆空间变量
4、静态变量
5、常量 函数指针#xff1a;
指向函数的指针#…目录
函数指针 指针函数
参数为指针的函数
参数为数组的函数
C语言内存管理 stdlib.h头文件常用函数介绍
1、局部变量 2、全局变量
3、 堆空间变量
4、静态变量
5、常量 函数指针
指向函数的指针称为函数指针
void f (int); // 函数 f 的类型是 void (int)
void (*p)(int); // 指针 p 专门用于指向类型为 void (int) 的函数p f; // p 指向 f取址符可以省略
p f; // p 指向 f// 以下三个式子是等价的f (666); // 直接调用函数 f
(*p)(666); // 通过索引指针 p 的目标间接调用函数 fp (666); // 函数指针在索引其目标时星号可以省略指针函数
指针函数就是返回指针值的函数本质是一个函数。
//一般定义方法有以下三种格式
int *fun(int x,int y);
int * fun(int x,int y)
int* fun(int x,int y);一般在申请堆空间的时候函数需要返回一个指针例如
int *get_memory(int size)
{int *p malloc(sizeof(int) * size);printf(分配的堆空间地址 %p\n, p);return p;
}
参数为指针的函数
函数有形参和实参之分如何通过形参改变实参呢
函数的传递分为两种一种是值传递一种是地址传递
参数的值传递,形参与实参相互独立互不影响。
参数的地址传递,形参可以通过地址修改实参的数据。通过函数的地址传递的解引用才能修改实参的数据
有以下三种情况
#include stdio.hvoid swap(int a, int b)
{int temp a;a b;b temp;printf(swap中a%d, b%d\n, a, b);
}int main()
{int a 100, b 200;swap(a, b);printf(main函数中a%d, b%d\n, a, b);return 0;
}这是一个简单的交换函数输出如图 可以看到在main函数中函数的值实际上是没有交换的这就是函数的值传递
第二种情况
#include stdio.hvoid swap_addr(int *a, int *b)
{printf(swap函数中交换之前 a%p,b%p\n, a, b);printf(swap函数中交换之前 *a%d,*b%d\n\n, *a, *b);int *tmp a; // 只是交换了两个指针所指向的地址而已并不是交换地址上的内容(数据)a b;b tmp;printf(swap函数中交换之后 *a%d,*b%d\n, *a, *b);printf(swap函数中交换之后 a%p,b%p\n\n, a, b);
}int main()
{int a 100, b 200;printf(main函数中交换之前 a%p,b%p\n, a, b);printf(main函数中交换之前 a%d, b%d\n\n, a, b);swap_addr(a, b);printf(main函数中交换之后 a%p,b%p\n, a, b);printf(main函数中交换之后 a%d, b%d\n, a, b);return 0;
}输出如图 这种情况虽然是函数的地址传递但是main函数中的值仍然没有变化这就是因为我们只对地址进行了交换没有对地址中的值解引用交换
所以第三种情况时对swap_addr()函数进行修改
void swap_addr_new(int *a, int *b)
{int tmp *a; *a *b;*b tmp;
}可以看到main函数中的值被成功修改 参数为数组的函数
在函数形参为数组时编译器为了节省内存空间会自动将数组转换为指向数组首地址的指针
如
int arry_sum(int arry[5]) 等价于 int arry_sum_x(int *arry)
正常由于arry是含有五个元素的int型数组所以sizeof(arry)等于20但由于函数中arry[5]是一个指针所以在函数中sizeof(arry)等于8
二维数组同理
int two_arry_sum(int arr[3][3]) 等价于 int two_arry_sum_x(int (*arr)[3]) 等价于 int two_arry_sum_x(int (*)[3])
C语言内存管理
可以参考这篇文章写的非常详细这里只做总结和补充 C语言 内存管理 - 知乎 (zhihu.com) stdlib.h头文件常用函数介绍 #include stdlib.h---------分配----------void *malloc(size_t size); //分配大小为size 的堆空间 void *calloc(size_t nmemb, size_t size); //分配大写为 size * nmemb 的堆空间 ---------修改---------- void *realloc(void *ptr, size_t size); //修改ptr的堆空间大小为 sizevoid *reallocarray(void *ptr, size_t nmemb, size_t size);//修改ptr的堆空间大小为 size * nmemb---------释放---------- void free(void *ptr); //释放ptr 所指向的堆空间
1、局部变量
局部变量:自动分配空间自动释放空间 存储区:栈空间 定义:在函数内部的 花括号定义 { }作用域:只在当前 花括号{ } 内有效 生命周期: 只在当前 花括号{ } 内有效 2、全局变量
全局变量: 在整个程序中都一直存在 存储区:数据段 定义:在所有的函数外面定义 作用域:在整个程序中都有效 生命周期:在整个程序中都有效
#include stdio.hint a 10, b 20;void swap_all()
{printf(swap函数中全局变量地址 a%p,b%p\n, a, b);printf(swap函数中全局变量交换前 a%d,b%d\n, a, b);int tmp a;a b;b tmp;printf(swap函数中全局变量交换后 a%d,b%d\n\n, a, b);
}int main()
{swap_all(a, b);printf(main函数中全局变量 a%d, b%d\n, a, b);return 0;
} 输出结果 但是如果在main函数中重新定义 int a,b;则main函数会输出其中的局部变量因为局部变量在本函数中优先级大于全局变量。
3、 堆空间变量
堆空间变量: 由用户自己去管理空间 (最灵活的内存空间)存储区:堆空间 定义:调用 malloc,calloc 进行分配 作用域:在空间未被释放之前都有效 生命周期:利用 malloc,calloc 分配 利用 free 释放 int *Heap()
{// int value 100; //会释放不能返回int *value malloc(sizeof(int));// 8个局部变量的指针空间 4个堆空间变量 12 个空间*value 100; // 往堆空间存储数据printf(value%p,*value%d\n, value, *value);return value; // 返回堆空间没问题 , 指针会释放 堆不会// return value;
} //在堆内存中申请一个空间依次存入元素
#include stdio.h
#include stdlib.hvoid *size1(int size)
{int *p (int *)malloc(sizeof(int) * size);return p;
}int main()
{int size5;int *q size1(size);for(int i 0; i5; i){ q[i] i;printf(%d\n, q[i]);}} 内存释放和内存泄露
int *Heap_tmp()
{int *tmp malloc(sizeof(int));*tmp 100;printf(tmp%p,*tmp%d\n, tmp, *tmp);// 内存泄漏堆空间的地址已经找不到了// 注意:如果在一个函数中使用了堆空间 记得释放 或者 把空间地址返回出去否则会出现内存泄漏
}
需要添加free()函数
4、静态变量
静态变量:在整个程序中都一直存在存储区:数据段 定义:利用 static 关键字定义 作用域:在整个程序中都有效 生命周期:在整个程序中都有效
静态局部变量
1.静态局部变量只能被初始化1次 存储在数据段不会释放。
#include stdio.hvoid increment() {static int count 0; // 静态局部变量count;printf(Count: %d\n, count);
}int main() {increment(); // 第一次调用count 初始化为 0然后加 1输出 1increment(); // 第二次调用count 不再初始化直接加 1输出 2increment(); // 第三次调用count 继续加 1输出 3return 0;
}
2.静态全局变量只能在当前文件使用无法跨文件使用防止全局变量名冲突。
5、常量
常量:在整个程序中都一直存在存储区:数据段 定义:利用 const 关键字定义 作用域:在整个程序中都有效 生命周期:在整个程序中都有效