指针

1指针定义

1、定义一个指针变量p,类型是int*。
2、p指向一个int型的数据【涉及的指针符号:* &】
int *p;

2指针的绑定

p = &a;
//指针的解引用,*p得到了变量(a)。
*p = 23;

3指针的初始化【定义指针的同时 应该并且初始化】

int *p1 = &a;	// == int *p, a; p = &a
【int *p=NULL】专用于指针的初始化

注意【指针的运算,就是指针所指向的变量类型所占字节大小(sizeof(int)) * 1】

野指针危害:

1、直接指向内核区 
2、指向可用也没有别的数据的区域 
3、最可怕,可用但有别的数据

const

1【const与指针, 就近原则】

【1】int const *p1;
    p1 = &a;
    *p1 = 11; // 错误  error: assignment of read-only location ‘*p1’【p1指向的内容不可改变,但是p1所指向的地址可以改变】

【2】const int    *    p2; // p2 ,p2所指向的数据(int) 等同于p1

【3】int * const p3;	      // 野指针 修饰p3,p3不可改, 也就是说p3所指向的内容可改变

【4】const int *const p4;  // 必须定义时 同时初始化  两者都不能变

2【const 关键字, 修饰的变量是常数,不可更改。只能初始化一次】

函数的输出型参数

1、数组名作为函数参数退化为一个指针
 2、子函数内部改变了原数组里面的内容

举例 【主函数省略】

void func_arr(int *arr, int lenth) // == (int arr[]) == (int arr[数字]) { printf("arr = %p. sizeof(arr) = %d.\n", arr, sizeof(arr));

*arr = 11; // == arr[0] = 11
arr[1] = 22;		

}

【不用返回值也可以改变主函数的值】

数组与指针

【1】【不太理解】

int *p1 = &arr[0];
printf("*p++ = %d.\n", *p++)【】
printf("*(p++) = %d.\n", *(p++));
printf("*++p = %d.\n", *++p);
printf("(*p)++ = %d *p = %d.\n", (*p)++, *p);
printf("*p = %d (*p)++ = %d.\n", *p, (*p)++);	 
printf("*p = %d.\n", *p);

int *q = arr + 5;	
// 同一数组,指针相减是个数
int ret = q - p;

【2】二维数组

二维数组, 变量名:首元素首地址{arr[0], arr[1]} //arr &arr[0] &arr[0][0] //arr代表数组首元素首地址(&arr[0]) //&arr[0]代表第一维数组的首元素首地址 //&arr[0][0]代表数组的第二维数组是首元素首地址 int arr[2][3] = {1, 2, 3, 4, 5, 6};

//数组指针, 指针指向了一个int[3]类型的数据结构
int (*p)[3]

typedef

【/typedef是重命名的关键字,他不是发明新类型,而是给类型起了一个新外号】

函数是一个地址,也就可以理解成指针,所以函数也可以 //用类型这个理解方法 //类型名 + 变量名 //定义一个函数指针, 并且绑定, C语言里对于函数名的绑定有两种方式: //func、&func,通常写成func void (*p)(void) = &func; //调用函数, 指针的解引用

malloc动态数组

1 malloc堆申请的空间,【默认是有最小分配的】

int *p = NULL
p = (int *)malloc(num * sizeof(int));

2 判断申请空间是否成功

if (NULL == p)
{
	printf("malloc error.\n");

	return -1;
}	

3 清空这段内存

memset(p, 0, num*sizeof(int));

4释放堆内存

1、整个程序结束,会自动释放堆内存
2、申请一次,释放一次,不能多次释放
3、释放的堆内存必须是这块内存的首地址
if (NULL != p)
{
	free(p);
	//p就是一个野指针
	p = NULL;
}

return 0;

}