C语言基础(四)(指针)
程序员文章站
2024-03-07 16:37:39
...
一、指针基础
1、定义、绑定、和解引用
- 定义一个指针变量p,类型是int* ,指向一个int型的数据 :
int *p = NULL;///NULL代表指向空,即什么都不指向,等同于int类型的0;避免野指针。
- 绑定一个int型变量a:
int a = 0;
int *p = &a;//指针变量内存储的是地址,故绑定非地址变量时需要使用取地址符号&
- 指针的解引用
int a = 0;
int *p = &a;
*p = 6; ///将p指向的地址,即a的值赋值为6。*为解引用符号。
2、指针的相减
- 1、指针变量只能相减,不能加乘除。
- 2、两指针变量相减,结果为int类型,数值为两指针指向的地址之差除以sizeof(变量类型),变量类型为指针所指向的数据的类型。
- 3、若相减的两指针在同一数组中,贼相减的结果 == 两指针指向的元素的下标之差。
3、野指针
- 野指针的危害(从低到高):
1、直接指向内核区,即当前进程所使用的区域,可以随意修改。
2、指向可用也没有别的数据的区域 。
3、最严重,可用但有别的数据 ,会修改其他正在运行中的进程的数据。
在定义一个野指针时随机发生以上情况的其中一种,所以在编程中,野指针应尽量避免
二、指针的应用
1、指针函数
#include<stdio.h>
void func(unsigned short *a);
int main(void)
{
unsigned short a = 0x11ff;
func(&a);
printf ("%x\n", a);
}
void func(unsigned short *a)
//在传输参数时,传来的是指针,即a的地址,所以在子函数中,*a的运算改变的是a所指向的地址的值,故可以影响到主函数的值(可以直接对数组进行赋值也是一个道理)。
{
unsigned short b = *a;
*a = *a << 8;
b = b >> 8;
*a += b;
}
2、函数指针
#include<stdio.h>
void func(unsigned short *a);
int main(void)
{
unsigned short a = 0x11ff;
void (*p)(unsigned short *a) = &func;//&func 或 func都可以。
(*p)(&a); //(*p)(&a) 或 p(&a)都可以。
printf ("%x\n", a);
}
void func(unsigned short *a)
{
unsigned short b = *a;
*a = *a << 8;
b = b >> 8;
*a += b;
}
3、指针数组
- 即定义一个数组,该数组的每一个元素都是一个指针。
#include<stdio.h>
int main(void)
{
int arr[5] = {1, 2, 3, 4, 5}, i = 0;
int *p_arr[5] = {}; ///指针数组。
for (i=0; i<5; i++)
p_arr[i] = &arr[i];
printf("%d.\n", *p_arr[2]);
}
4、数组指针
- 定义一个指针,该指针指向的数据是一个数组型的数据。(即自加一会越过整个数组)
#include<stdio.h>
int main(void)
{
int arr[2][3] = {1, 2, 3, 4, 5, 6};
int (*p)[3] = &arr[0] + 1; ///数组指针
printf("%d.\n", **p); //输出为a[1][0]的值:4
}
三、相关命令
1、malloc函数
- 头文件:
#include <stdlib.h>
- 命令格式:
int *p = (int *p)malloc(数字)//申请时默认返回void *
- 堆内存也是内存的一种,需要程序员自己手动申请malloc,手动释放 。
编译器不会自动回收,申请的内存伴随整个程序 。
malloc申请的空间,默认是有最小分配的。
流程:申请,判断成功,初始化,使用,释放,指针设置为空 。
2、typedef
- typedef的作用是定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象。
- typedef可以在全局定义,也可以在函数中定义。
typedef int my_int//将int重命名为my_int
typedef char * my_char_p//将char *重命名为my_char_p
typedef (void (*p)(void)) my_func//将void * void 类型的函数重命名为my_func
3、const 关键字
- const 修饰的变量是常数,不可更改,只能初始化一次;但可以用指针解引用修改。
#include <stdio.h>
void main(void)
{
const int a = 0;
a = 3; //错误,不可以直接修改内容
int *p = &a;
*p = 2; //正确,可以通过指针更改内容
printf ("%d", a);
return;
}
四、二维数组
- 定义:
int a[2][3]; //代表定义一个int型的二行三列的数组。
- 二维数组的变量名是首元素首地址{arr[0], arr[1]}
- &arr代表第一维数组的首地址。
- &arr[0]、arr 代表第一维数组的首元素首地址,第二维数组的首地址。
- &arr[0][0]、arr[0] 代表数组的第二维数组是首元素首地址。
五、二重指针
- 二重指针指向的是一重指针的地址,一重指针不能指向一重指针的地址。
- 二重指针的使用:
#include <stdio.h>
void func (int **p);
void main (void)
{
int **q = NULL, *p = NULL;
int a = 11;
p = &a;
q = &p;
func (q);
printf("*p = %d\n", *p); // *p = 22
printf("**q = %d\n", **q); // **q = 0
}
void func (int **p)
{
int a = 22;
*p = &a;
}
上一篇: IP查询系统的异步回调案例