定义
- 如何定义指针变量
/*
数据类型 * 变量名称
数据类型:表示指针变量能够保存什么类型的变量地址;
* : 没有任何特殊含义,仅仅为了表示这是一个指针变量
*/
int num = 10;
int * p;
p = & num; //指针变量只能保存地址
//int * p = #
printf("num = %d \n",num);//num = 10
printf("p = %p \n", p);//p = 0x7ffeefbfef1c
printf("&num = %p \n", &num);//&num = 0x7ffeefbfef1c
printf("*p = %d \n",*p);//*p = 10
//*p : 表示访问访问 p 指向的那块内存空间
复制代码
基本数据类型
作为函数的参数是值传递
, 在函数中修改形参的值不会
影响到外面实参的值数组
作为函数的参数是地址传递
, 如果是地址传递
在函数中修改形参的值会
影响到外面实参的值
指针注意点
- 指针只能保存地址
- 同一个变量可以有多个指针指向它
- 指针的指向可以修改
- 不要访问野指针
- 指针是什么类型,就只能访问什么类型的数据
指针与数组
- 数组名就是数组的地址 == 数组首元素的地址
int ages[3] = {1, 3 , 5};
printf("ages = %p\n", ages);//ages = 0x7ffeefbfef0c
printf("&ages[0] = %p\n", &ages[0]);//&ages[0] = 0x7ffeefbfef0c
复制代码
由于数组首元素地址即数组地址,定义一个指针指向数组,实际即定义一个指针指向数组的首元素,所以数组的首元素是什么类型,指向数组的指针就是什么类型
int * p1 = &ages[0];
int * p2 = ages;
printf("p1 = %p\n", p1);//p1 = 0x7ffeefbfef0c
printf("p2 = %p\n", p2);//p2 = 0x7ffeefbfef0c
复制代码
- 指针操作数组
// 指针操作数组
p1[2] = 90;
// ages = {1, 3 , 90};
复制代码
- 通过指针 + 1 遍历数组
- 指针+1, 并不是真实的+1, 而是+4(4个字节),
- 指针的两个用途
- 取值的时候, 会根据指针类型所占用的字节去取出对应字节的数据
- 用于做加法运算, 指针+1, 其实是加上指针类型所占用的长度 , 如果当前指针类型是int, 那么+1本质上是加上4个字节
printf("p1+0 = %d\n", *(p1 + 0));//1
printf("p1+1 = %d\n", *(p1 + 1));//2
printf("p1+2 = %d\n", *(p1 + 2));//90
复制代码
指针与字符串
- 数组保存字符串和指针保存字符串的区别
- 数组保存的字符串,字符串是一个
变量
str可以修改
- 指针保存的字符串,字符串是一个
常量
str不可修改
- 数组保存的字符串,存储在
栈
中;指针保存的字符串保存在常量区
- 存储在栈中的变量有一个特点, 当作用域结束系统会自动释放该变量
- 存储在常量区中的值有一个特点, 不会被释放, 而且多个相同的值对应的地址相同
- 数组保存的字符串,字符串是一个
// 保存字符串
char str[] = "wcl";
printf("str = %s\n", str);//wcl
str[0] = 'm';
printf("str = %s\n", str);//mcl
//数组名就是数组的地址, 数组名保存的就是数组的第0个元素的地址,所以我们可以使用指针来保存字符串
//通过指针保存一个字符串, 其实就是保存的字符串第0个元素的地址
char * str1 = "wcl";
printf("str1 == %p\n",str1);//0x100003f50
// str1[1] = 'j';//Thread 1: EXC_BAD_ACCESS
printf("*str1 = %c\n", *str1);//w
printf("*str1 = %c\n", *(str1 + 1));//c
printf("*str1 = %c\n", *(str1 + 2));//l
printf("*str1 + 0_p = %p\n", &(*str1));//0x100003f50
printf("*str1 + 1_p = %p\n", &(*(str1 + 1)));//0x100003f51
printf("*str1 + 2_p = %p\n", &(*(str1 + 2)));//0x100003f52
printf("sizeof(*str1) = %ld\n", sizeof(*str1));//1
printf("sizeof(str1) = %ld\n", sizeof(str1));//8
char * str2 = "wcl";
printf("str2 == %p\n",str2);//0x100003f50
复制代码
练习:自定义方法计算字符串的长度
int myStrlen(char *str) {
int count = 0;
while (*str != '\0') {
printf("str_p == %p \n",str);
/**
str_p == 0x100003f9e
str_p == 0x100003f9f
str_p == 0x100003fa0
str_p == 0x100003fa1
str_p == 0x100003fa2
str_p == 0x100003fa3
*/
str = str + 1;
count ++ ;
}
/**
\0 ascii 0 // 0代表假 1真
while (*str++)count++;
*/
return count;
}
复制代码
函数指针
- 函数会占用一块存储空间,所以函数也有自己的地址
- 函数的地址保存在函数名中,函数名就是函数的地址(数组名就是数组的地址);
函数指针的定义方式
return_Type (*functionP)(arg_type);
* : 表示一个指针;
functionP : 表示指针的变量名称;
(*function) : 表示将来指向一个函数;
return_Type : 表示指向的函数返回值类型;
(arg_type) : 表示指向的函数参数类型;
复制代码
void test()
{
printf("test被执行了\n");
/*
void (*functionP)();
* : 表示一个指针;
functionP : 表示指针的变量名称;
(*function) : 表示将来指向一个函数;
void : 表示指向的函数没有返回值;
() : 表示指向的函数没有参数
*/
}
int getAge()
{
return 20;
}
void sum(int v1, int v2)
{
int res = v1 + v2;
printf("res = %i\n", res);
}
int sum2(int v1 , int v2)
{
int res = v1 + v2;
return res;
}
int main(int argc, const char * argv[]) {
printf("test_p = %p\n",test);//0x100003f10
//没有返回值,没有参数
void(*test_P)(void);
//void(*test_P)(void) = test;
test_P = test;
test_P();
//有返回值,没有参数
int (*ageP)();
ageP = getAge;
printf("age = %i\n", ageP());
//有参数,没有返回值
void (*sumP)(int, int);
sumP = sum;
sumP(10, 20);
//有返回值,有参数
int (*sumP2)(int , int);
sumP2 = sum2;
printf("sum = %i\n", sumP2(10, 20));
return 0;
}
复制代码
函数作为参数
int sum(int v1, int v2)
{
return v1 + v2;
}
int minus(int v1, int v2)
{
return v1 - v2;
}
/// action方法
/// @param v1 V1
/// @param v2 V2
/// @param function 函数指针
int action(int v1,int v2,int(*function)(int,int)) {
int result = function(v1,v2);
return result;
}
int main(int argc, const char * argv[]) {
int(*function_1)(int,int) = sum;
int(*function_2)(int,int) = minus;
// int sum_v = action(10, 20, function_1);
// int minus_v = action(20, 10, function_2);
int sum_v = action(10, 20, sum);
int minus_v = action(20, 10, minus);
printf("sum_v = %d,\nminus_v = %d\n",sum_v,minus_v);
return 0;
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END