指针的基本使用与实现
一、前言
以下代码均有vs2013实现,vs可以看到内存空间,对于指针学习更加方便。
二、代码实现
堆内存使用
void use_malloc()
{
int len;
char *p;
printf("请输入要申请的空间大小:");
scanf("%d", &len);
/*申请的空间是按字节给的,malloc返回的类型是void*必须对其进行强转*/
p = (char*)malloc(len);
strcpy(p, "hello");//对申请到的空间进行赋值时必须使用strcpy
puts(p);
/*p++不对,释放时指针不能偏移,要存最初的位置,
free时给free的指针必须是malloc最初返回的*/
free(p);//必须要对申请到的空间进行释放
}
栈空间与堆空间
char* stack_string()
{
char c[10] = "hello";
puts(c);
return c;
}
char *heap_string()
{
char *p = (char*)malloc(10);
strcpy(p, "hello");
return p;
}
void stack_heap()
{
char *p;
p = stack_string();
printf("%s\n", p);/*这是栈空间无法通过地址返回hello,
因为栈空间函数运行后会释放地址空间*/
p = heap_string();/*这是堆空间返回的地址,堆空间不会被自动释放
所以可以显示hello*/
printf("%s\n", p);
}
字符指针和字符数组初始化
void pointer_init()
{
char *p = "hello";//字符串常量的地址赋值给了p
char c[10] = "hello";//相当于把字符常量复制了一份给p
c[0] = 'H';//可以更改
//p[0] = 'H'//不能更改因为p存放的是字符串常量,字符串常量不能更改
p = "world";//正确,因为可以更改p指向的地址
}
野指针
void wild_point()
{
int *p1, *p2, *p3;
p1 = (int*)malloc(4);
free(p1);
p2 = (int*)malloc(4);
free(p2);
p3 = (int*)malloc(4);
*p3 = 3;
printf("%d\n", *p3);
/*野指针的产生是因为指针释放后没有赋值NULL,导致指针依然指向
被释放了的空间。当其他指针申请空间后野指针仍然能够操作已被释放的空间*/
*p1 = 300;
printf("%d\n", *p3);
}
const的使用
void use_const()
{
/*const int PI=3可以看做与#define PI 3相似都是无法更改PI的
但是const用PI给其他值赋值时,不会增加空间,相当于给的地址。
而define用PI给其他值赋值时,其他值会重新开辟空间*/
char str1[] = "helloworld";
char str2[] = "beautiful";
char *const p1 = str1;/*指针内存储的地址不能修改,即使++也不行,
但可以修改指向的内容*/
p1[2] = 'k';//这个是可以的
const char *p2 = str1;/*指针存储的地址可以修改,但是不能修改
指向地址中的内容*/
}
自己实现memmove
void mymemmove(void *to,void* from,size_t count)
{
char *pfrom, *pto;
if (from > to)
{
pfrom = (char*)from;
pto = (char*)to;
while (count)
{
*pto = *pfrom;
pto++;
pfrom++;
count--;
}
}
else if (from<to)
{
pfrom = (char*)from + count-1;
pto = (char*)to + count - 1;
while (count)
{
*pto = *pfrom;
pto--;
pfrom--;
count--;
}
}
}
//memcpy与memmove
void use_memmove()
{
int a[5] = { 1, 2, 3, 4, 5 };
int b[5] = { 1, 2, 3, 4, 5 };
//注意mem系列是按字节进行处理的
mymemmove(a+2,a,sizeof(int)*3);
memmove(b + 2, b, sizeof(int)* 3);
}
数组指针
void use_pointrer()
{
//注意任何一个指针都是占四个字节的地址空间
//一级指针就是指指针,就是内存地址,二级指针就是指向指针的指针,就是地址的地址
int a[][4] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 10, 11, 13 };
/*数组指针是一级指针,对数组使用。
数组指针(也称行指针)定义 int (*p)[n];()优先级高,
首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,
也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。*/
int *q,(*p)[4];
q = a;//p[0][2]已经不是指针了,此方法定义后的指针可当二维数组a使用
p = a;
int i = 10;
}
main函数
int main()
{
//指针变量存储的是地址,*p表示存储地址所对应的值
//指针本质是为了间接访问(传递和偏移)
//函数调用本质是值传递
//堆内存使用
//use_malloc();
//栈空间与堆空间
// stack_heap();
//字符指针和字符数组初始化
//pointer_init();
//野指针
//wild_point();
//const的使用
//use_const();
//memcpy与memmove
//use_memmove();
//数组指针,偏移一个数组的大小
use_pointrer();
system("pause");
}