1,指针的基本概念与定义
指针(Pointer)利用地址,它的值直接指向存在电脑存储器中另一个地方的值
例如:
int * p;
这句代码的意思是:1、定义一个指针变量p,类型是int*。2、p指向一个int型的数据
p = &a;
指针的绑定
*p;
指针的解引用,*p得到了变量值
int *p1 = &a
定义指针的同时并且初始化
p1++;
指针的运算,就是指针所指向的变量类型所占字节大小(sizeof(int)) * 偏移量
2,const关键字
修饰的变量是常数,不可更改,只能初始化一次。、
例如:const int a = 23;
则a就被规定好是常量23,不可更改。
3,数组中指针的应用
int arr[5] = {1, 3, 5, 7, 9};
//arr作右值
int *p = arr;
printf("*(p++) = %d.\n", *(p++)); //打印出1,因为++在后面,遇到“;”结尾才+1运算
printf("*++p = %d.\n", *++p); //打印出3
int *q = arr + 5;
// 同一数组,指针相减是个数
int ret = q - p;
printf("ret = %d.\n", ret); //打印出5
4,指针的调用
传址调用
#include <stdio.h>
void func2(int *p)
{
printf("p = %p.\n", p);
*p = 23;
}
int main(void)
{
int a = 11;
printf("&a = %p.\n", &a);
//传址调用
func2(&a);
printf("a = %d.\n", a);
return 0;
}
上例可以看到,主函数中a的地址与子函数中指针p的地址相同,且a的值变为23;这就是传址调用
指针函数
带指针的函数,即函数返回类型是某一类型的指针
#include <stdio.h>
int * func1(int a)
{
//int a相当于局部变量,函数调用结束就销毁
printf("&a = %p.\n", &a);
a = 23;
//不要返回局部变量的地址
return &a;
}
int main(void)
{
int val = 0;
printf("&val = %p.\n", &val);
int *p = func1(val);
printf("val = %d.\n", val);
printf("p = %p.\n", p);
}
val的值并未改变
数组中的调用
#include <stdio.h>
//1、数组名作为函数参数退化为一个指针 2、子函数内部改变了原数组里面的内容
void func_arr(int *arr, int lenth) //
{
printf("arr = %p. sizeof(arr) = %d.\n", arr, sizeof(arr));
*arr = 11; // == arr[0] = 11
arr[1] = 22;
}
int main(void)
{
int arr[3] = {2, 5, 8};
func_arr(arr, 3);
printf("arr[1] = %d. arr[0] = %d. \n", arr[1],arr[0]);
printf("in main arr = %p.\n", arr);
}
malloc函数
动态内存分配,当无法知道内存具体位置的时候,想要绑定真正的内存空间,就需要用到动态的分配内存
需要程序员自己手动申请malloc(写代码),自己手动释放
下面的程序就是一个申请动态数组,并冒泡排序的例子
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int * shenqing_memory(int num)
{
int *p = (int *)malloc(num*sizeof(int));
if (NULL == p)
{
return p;
}
//初始化清零
memset(p, 0, num*sizeof(int));
return p;
}
void set_value(int p[], int num)
{
int i = 0;
//一共赋值num次
printf("输入%d个元素数值:\n",num);
for (i=0; i<num; i++)
scanf("%d", p++);
}
//交换两个数值
void swap(int *p1, int *p2)
{
int temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
void func_arr(int *p, int lenth)
{
int i = 0, j = 0;
for (i=0; i<lenth-1; i++)
{
for (j=0; j<lenth-1-i; j++)
{
if (*(p+j) > *(p+j+1))
{
swap(p+j, p+j+1);
}
}
}
}
void arr_show(int *arr, int num)
{
int i = 0;
while (num--)
{
printf("%d ", *arr++);
}
printf("\n");
}
int main(void)
{
int num = 0;
printf("输入数组个数:");
scanf("%d", &num);
int *p = shenqing_memory(num);
//就可以使用这个内存了
//赋值这个数组
set_value(p, num);
//排序
func_arr(p, num);
//遍历函数
arr_show(p, num);
if (NULL != p)
{
free(p);
//p就是一个野指针
p = NULL;
}
return 0;
}
其中,memset是设置内存,要包含#include string头文件;默认的是void* 型,所以要强制类型转换为int*;参数第一个为要设置的内存的首地址,第二个为要设置的内容,第三个为内存整体大小
malloc要包含#include stdlib.h头文件,参数是要申请内存空间的大小,默认也为void*所以要强制类型转换