C语言指针进阶笔记

一、指针与二维数组

    两种角度看待二维数组

(1)从一维数组角度

#include 
int main()
{
    int a[3][4];
    int *p=&a[0][0];
    int i,j;
    for( i=0; i<3; i++ )
        for( j=0; j<4; j++ )
            *(p++)=i+j;//赋值以后,p++,向后移
}

(2)从二维数组角度

int a[3][4];
int (*p)[4];//或者int p[][4];
p = a;
for( int i=0; i<3; i++ )
    for( int j=0; j<4; j++ )
        *(*( p+i)+j) = i+j; 

二、动态分配内存

1、C语言内存管理

C语言指针进阶笔记_第1张图片

计算机中的内存是分区来管理的,程序和程序之间是独立的,不能互相访问。而每个程序的内存是分区管理的,分为代码区、静态区、堆区、栈区。

(1)代码区:所有的可执行代码都加载到代码区(含常量、子函数、main函数)

int num = 3;
// 只有 num = 3 这一部分被放到代码区

(2)静态区:存放全局变量和静态变量。这块内存在程序编译的时候就已经分配好了,在程序的运行期间都存在。

(3)栈区:

  ① 存放函数形参、局部变量,以及在进行任务切换时存放当前任务的上下文内容(函数调用的当前任务所使用的寄存器的值、函数调用前程序的下一条语句的地址)

  ② 形参和局部变量离开作用域 以后,栈上的内存会被自动释放。因此,函数不能返回局部变量的地址

( 把局部变量定义为 static 类型或者用 堆 可以解决这个问题 )

void function(int n)
{
    char s[] = "abc";
}
// int a 和 char s[] 均储存在栈区

(4)堆区:动态分配内存区

① 动态申请的内存在堆区。

② 函数返回指向局部变量的指针,如果是由malloc动态分配的内存指针,是合法的。

2、相关函数

注意:

① 使用时要加上 #include

② 动态申请内存以后,要free();

(1)malloc

分配一块长度为size字节的连续空间,并将该空间的首地址作为函数的返回值。如果函数没有成功执行,返回值为空指针(NULL或0)

void *malloc(unsigned int size);// 函数原型
int *p;
p=(int *)malloc(sizeof(int)); // 使用时记得类型转换
if( (int *)malloc(sizeof(int)) != NULL )// 安全起见建议这样使用
{
    ...
}

(2)calloc函数

int *p;
p=(int *)calloc(10,sizeof(int)); 
// 适合动态申请数组

(3)realloc函数(用得少)

void * realloc(void  *ptr, size_t  size);// 函数原型

// 改变ptr所指内存区域的大小为size长度
// 如果重新分配成功则返回指向被分配内存的指针,否则返回空指针NULL。

注意:

① 当分配内存成功之后,应将原本的指针ptr=NULL,否则会形成野指针,可能造成系统崩溃。 

② 重新分配的内存大于原有长度时,原来的内存块如果不够用,则会分配一块新的内存,原有的内存被释放。此时ptr指针就会变成野指针。如果长度小于原有长度则原有内容部分保持不变。

(4)用memset函数将malloc函数的存储空间初始化

#include 
#include 
#include 
int main(){
  int *ip;
  ip=(int *)malloc(10*sizeof(int));
  memset(ip,0,10*sizeof(int));// 初始化为 0 
  int i;
  for(i=0;i<10;i++){
     printf("0x%-10x",ip[i]);
     if (i==4)
        printf("\n");
  }
  free(ip);

(5)常见问题

① 原本指针地址变化了,找不到初始所得空间。

解决:将指针初始化为0,然后malloc,最后free(NULL)

② 程序结构不好,找不到 free 的时机

三、函数指针

1、定义

// 类型 ( *指针名 )( type )
double ( *funcPtr )( double,double );
int ( *fp )( int );

2、使用

int add( int num1, int num2 )
{
    return num1+num2;
} 

int result;
functPtr = add;
// Make functptr point to function add
result = (*functPtr)( 1,2 );
result = functPtr( 1,2 );
// The above two statements are equivalent

 

3、作为函数参数

#include 
int add(int num1,int num2)
{
    return num1+num2;
}
int sub(int num1,int num2)
{
    return num1-num2;
}


int caculate( int (*fp)(int,int),int num1,int num2)
{
    return (*fp)(num1,num2);
}
int main()
{
    int num1,num2;
    char Symbol;
    scanf("%d %c %d",&num1,&Symbol,&num2);
    if( Symbol=='+' )
    {
        printf("%d",caculate(add,num1,num2));
    }
    if( Symbol=='-' )
    {
        printf("%d",caculate(sub,num1,num2));
    }
    return 0;
}

 

你可能感兴趣的:(C语言,c语言,指针,内存管理)