程序开始执行时,OS就分配了内存,用来存放栈,假设分配了1M,实际局部变量和栈帧的分配是在运行时,如果运行时栈帧增长的大小超过预留的大小,如果有无穷递归,bad,所以在运行中是不允许栈增长的,超过预先分配的空间大小,就会导致崩溃。栈大小在开始运行的时候就已经固定了。
局部变量里,有个很大的数组,但是数组大小需要根据具体参数来定,这时需要用到堆(heap)。在应用程序的整个生命周期,大小是不固定的。ps:这里的堆和数据结构里的堆不同,此处堆为空闲的内存池。
动态分配的内存,不需要在整个生命周期都存在,需要人为手动释放。
如果堆上没有足够的空间分配,则会返回null。
分配内存的函数 malloc void* malloc(size_t size) calloc void* calloc(size_t num, size_t soze) realloc void* realloc(void* ptr, size_t size) 第一个参数:指向已分配内存的起始地址的指针 第二个参数:新的内存块大小
不能解引用一个void类型的指针-》转成特定类型的类型,再解引用,因为malloc函数只会返回一个void类型的指针,不关心存储内存的类型,需要类型转换。
malloc不会申请内存后,不会初始化,calloc会初始化为0.
realloc-可以修改内存块的大小
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n;
printf("press what you want to create number of array:");
scanf("%d", &n);
int *A=(int*)malloc(n*sizeof(int));
for (int i = 0; i < n; i++) {
A[i] = i + 1;
}
for (int i = 0; i < n; i++) {
printf("%d ", A[i]);
}
return 0;
}
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n;
printf("press what you want to create number of array:");
scanf("%d", &n);
int *A=(int*)calloc(n,sizeof(int));
for (int i = 0; i < n; i++) {
A[i] = i + 1;
}
for (int i = 0; i < n; i++) {
printf("%d ", A[i]);
}
return 0;
}
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n;
printf("press what you want to create number of array:");
scanf("%d", &n);
int *A=(int*)calloc(n,sizeof(int));
/*for (int i = 0; i < n; i++) {
A[i] = i + 1;
}*/
for (int i = 0; i < n; i++) {
printf("%d ", A[i]);
}
return 0;
}
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n;
printf("press what you want to create number of array:");
scanf("%d", &n);
int *A=(int*)malloc(n*sizeof(int));
/*for (int i = 0; i < n; i++) {
A[i] = i + 1;
}*/
for (int i = 0; i < n; i++) {
printf("%d ", A[i]);
}
return 0;
}
由此可见,malloc和calloc的区别在于,一个不会进行初始化,一个会初始化为0.
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n;
printf("press what you want to create number of array:");
scanf("%d", &n);
int *A=(int*)malloc(n*sizeof(int));
for (int i = 0; i < n; i++) {
A[i] = i + 1;
}
for (int i = 0; i < n; i++) {
printf("%d ", A[i]);
}
int* B = (int*)realloc(A, 2 * n * sizeof(int));
//free(A);
printf("Prev block add=%d,new add=%d\n", A, B);
for (int i = 0; i < 2*n; i++) {
printf("%d ", B[i]);
}
return 0;
}
利用realloc扩展数组大小,如果原先分配的空间地址相邻部分有足够的大小,会进行扩展,如果没有足够的空间大小,会在一个新的空间,并且把旧值拷贝过去。
只保留一半的数据:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n;
printf("press what you want to create number of array:");
scanf("%d", &n);
int *A=(int*)malloc(n*sizeof(int));
for (int i = 0; i < n; i++) {
A[i] = i + 1;
}
for (int i = 0; i < n; i++) {
printf("%d ", A[i]);
}
int* B = (int*)realloc(A, (n/2) * sizeof(int));
//free(A);
printf("Prev block add=%d,new add=%d\n", A, B);
for (int i = 0; i < n; i++) {
printf("%d ", B[i]);
}
return 0;
}
C/C++中如何创建和使用函数指针
#include<stdio.h>
int Add(int a, int b){
return a+b;
}
int main(){
int c;
int (*p)(int,int);//pointer to function that should take
//(int,int) as argument/parameter and return int
p=&Add;
c=(*P)(2,3);//解引用函数,然后传参;de-referencing and executing the function.
printf("%d\n",c);
return 0;
}
#include<stdio.h>
//int Add(int a, int b){
// return a+b;
//}
void printHello(){
printf("hello\n");
}
int main(){
void (*ptr)();
ptr=printHello;
prt();
return 0;
}
函数指针的使用场景
函数指针作为函数传参
#include<stdio.h>
void A(){
printf("hello\n");
}
void B(void (*ptr)()){ //function pointer as argument
ptr(); //call-back function that "ptr" points to
}
int main(){
void (*p)()=A;
B(p);
//以上两句等价于
//B(A); //A此时就是回调函数,函数B可以通过函数指针来回调A
}
为什么B要间接地通过指针来调用A
普通冒泡排序
#include<stdio.h>
void bubbleSort(int *A,int n)
{
int i,j,temp;
for(i=0;i<n;i++){
for(j=0;j<n-1;j++){
if(A[j]>A[i]){//compare A[j] with A[j+1] and Swap if needed
temp=A[j];
A[j]=A[j+1];
A[j+1]=temp;
}
}
}
}
int main()
{
int A[]={3,2,1,5,6,4};//sort in increasing order=>{1,2,3,4,5,6}
BubbleSort(A,6);
for(i=0;i<6;i++){
printf("%d ",A[i]);
}
return 0;
}
使用函数指针
#include<stdio.h>
//callback function should compare two integers, should return 1 if first element has
//higher rank, 0 if elements are equal and -1 if second element has higher rank
int compare(int a,int b)
{
if(a>b)
return 1;
else
return -1;
}
void bubbleSort(int *A,int n,int (*compare)(int,int))
{
int i,j,temp;
for(i=0;i<n;i++){
for(j=0;j<n-1;j++){
if(compare(A[j],A[i])>0){
temp=A[j];
A[j]=A[j+1];
A[j+1]=temp;
}
}
}
}
int main()
{
int A[]={3,2,1,5,6,4};//sort in increasing order=>{1,2,3,4,5,6}
BubbleSort(A,6,compare);
for(i=0;i<6;i++){
printf("%d ",A[i]);
}
return 0;
}
待比较的元素通过引用来传,地址通过指针传递
const关键字不能修改指针指向的值,使用void指针因为qsort函数是通用的设计,qsort能够对任何数组排序,不仅仅是整型数组,只是需要给出循环逻辑。
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
//callback function should compare two integers, should return 1 if first element has
//higher rank, 0 if elements are equal and -1 if second element has higher rank
//int compare(int a,int b)
/*{
if(a>b)
return 1;
else
return -1;
}*/
int absolute_compare(int a, int b)
{
if(ads(a)>abs(b))
return 1;
return -1;
}
void bubbleSort(int *A,int n,int (*compare)(int,int))
{
int i,j,temp;
for(i=0;i<n;i++){
for(j=0;j<n-1;j++){
if(compare(A[j],A[i])>0){
temp=A[j];
A[j]=A[j+1];
A[j+1]=temp;
}
}
}
}
int compare(const void* a, const void* b)//const关键字不能修改指针指向的值,使用void指针因为qsort函数是通用的设计,qsort能够对任何数组排序,不仅仅是整型数组
{
int A=*((int*)a);
int B=*((int*)b);
return A-B;
}
int main()
{
int A[]={3,2,1,5,6,4};//sort in increasing order=>{1,2,3,4,5,6}
//BubbleSort(A,6,compare);
BubbleSort(A,6,absolute_compare);
qsort(A,6,sizeof(int),compare);
for(i=0;i<6;i++){
printf("%d ",A[i]);
}
return 0;
}
Conclusion:
内存地址 计算机内存~字节数组,每个字节有唯一的地址。 按字节可寻址,寻址的最小数据对象是一个字节。
小端存储,大端存储
指针
来源于B站fengmuzi2003的视频分享,仅供自学。