C中指针的理解

定义

  • 如何定义指针变量
/*
数据类型 * 变量名称

数据类型:表示指针变量能够保存什么类型的变量地址;
  *   : 没有任何特殊含义,仅仅为了表示这是一个指针变量
*/
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
喜欢就支持一下吧
点赞0 分享