指针基础总结

初级指针

指针概念

指针是内存中一个最小单位元的编号,也就是地址,口语中说的指针通常是指指针变量,指针变量就是一个变量,是用来存放地址的变量,地址是唯一表示一块地址空间的

指针的大小在32位平台是4个字节,64位是8个字节

指针和指针类型

1.指针类型决定指针在被解引用是访问几个字节

如果是int*的指针,解引用访问4个字节

如果是char*的指针,解引用访问1个字节

以此推广

2.指针的类型绝决定了指针+1或-1操作的时候跳过几个字节,决定了指针的步长

例如: int* pc

pc --访问4个字节

pc + 1 --跳过四个字节

const修饰指针

const int* p和 int const *p 都是修饰 *p,使 *p是不能改变的定值

int* const p; 是使p指向的地址是不可以改变的

野指针

野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)

1.野指针的成因

(1). 指针未初始化(存贮的是随机值)

可以初始化为NULL

int main()
{
     int* p;        //这里没有对指针进行初始化,可以写成int* p = NULL;
     *p = 10;         
     return 0;
}

(2).指针的越界访问

int mian()
  {
 
  int arr[10] = { 0 };
  int* p = arr;
  int i;
  for (i = 0; i <= 10; i++)    //指针指向的范围超出arr范围就会形成野指针
  {
      *p = i;
      p++;
  }
  return 0;​
  }

代码中,当i取到10时是第十一个元素,但是p只有10个空间,就会形成越界

3).指针指向的空间被释放

int* test()
  {
  
  int a = 10;
  return &a;​
  }
  int mian()
  {
  
  int* p = test();      //如果下一步对p进行使用,就会形成野指针,因为test所创建的地址在函数被调用后就不属于当前程序了(内存还在)但是p还保存的是被清除的地址
  return 0;

指针运算

1.指针加减整数

define NUM 5
  ​
  int main()
  {
  ​
  int arr[NUM];
  int* pa;
  for (pa = &arr[0]; pa < &arr[NUM];)
      *pa++ = 0;          //将arr数组值全赋值为0
  return 0;
  }

2.指针减去指针(不是所有的指针都能相减)

指向同一块空间的指针才能相减

指针减去指针得到的绝对值是指针和指针之间元素的个数

define NUM 10
  ​
  int main()
  {
  int arr[NUM];
  printf("%d", &arr[9] - &arr[0]);        //输出结果为9
  return 0;
  }

strlen手写

方法一

int my_strlen1(char* str) {
  int num = 0;
  for (; *str != '\0'; str++)
      num++;
  return num;
  ​
  }

方法二

int my_strlen2(char* str) {
  ​
  char* strat = str;
  while (*str != '\0')
      str++;
  return str - strat;  ​
  }

指针相加没有意义

3.指针的运算关系

允许指向数组元素的指针与指向数组最后一个元素后面的Negev内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较.

正确写法:

#define N_VALUES 5

int main()

{

    float values[N_VALUES];
    float* va;
    for (va = &values[N_VALUES]; va > &values[0];) {
    	*--va = 0;
    }
    for (int i = 0; i < 5; i++)
    	printf("%d ", values[i]);
    return 0;

}

错误写法: 

define N_VALUES 5
  ​
  int main()
  {
  float values[N_VALUES];
  float* va;
  for (va = &values[N_VALUES - 1]; va >= &values[0];va--) {        //这种写法是错误的
      *va = 0;
  }
  ​
  return 0;
​
  }

指针和数组

数组可以通过指针来访问

int main()
  ​
  {
  ​
      int arr[10] = { 0 };
      int* p = arr;
      int sz = sizeof(arr) / sizeof(arr[0]);
      for (int i = 0; i < sz; i++)
          printf("%d ", *(p + i));
      return 0;
  ​
  }

arr[i] = *(arr + i) = *(p + i)

二级指针

int a = 10; int

int* pa = &a; int * (*说明pa是指针,int说明所指的地址是int类型)

int** ppa = &pa; int * * ( *说明ppa是指针,int *说明所指的地址是int *类型)

指针数组

存放指针的数组就是指针数组

数组传递的是首地址,但是两个例外

1.sizeof(数组名),这里的数组名表示整个数组

2.&数组名,这里的数组名表示的依然是整个数组

int main()
  ​
  {
  ​
      int arr[10] = { 0 };
      printf("%p\n", arr);
      printf("%p\n", arr + 1);         //跳过四个字节
      
      printf("%p\n", &arr[0]);
      printf("%p\n", &arr[0] + 1);    //跳过四个字节
      
      printf("%p\n", &arr);
      printf("%p\n", &arr + 1);       //跳过整个数组
  ​
      return 0;
  ​
  }
  以下图片是上述代码输出的地址
  
  
int main()
  {
  int a = 10;
  int b = 20;
  int c = 30;
  int arr[10];
  int* pa = &a;
  int* pb = &b;
  int* pc = &c;
  int* parr[10] = {&a,&b,&c};
  ​
  for (int i = 0; i < 3; i++) {
      printf("%d ", *parr[i]);
  }
  return 0;
  }

使用指针数组模拟二维数组

//正常二维数组
  int main()
  {
      int arr[3][4] = { 1,2,3,4,2,3,4,5,3,4,5,6 };
      for (int i = 0; i < 3; i++) {
          for (int j = 0; j < 4; j++) {
              printf("%d ", arr[i][j]);
          }
          printf("\n");
      }
      return 0;
  }
//模拟实现
  int main(){
    int arr[4] = { 1,2,3,4 };
    int brr[4] = { 2,3,4,5 };
    int crr[4] = { 3,4,5,6 };
    int* p[3] = { arr,brr,crr };
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 4; j++) {
            printf("%d ", p[i][j]);    //*(*(p + i) + j),对(p + i)解引用分别找到arr,brr,crr首地址
        }
        printf("\n");
    }
    return 0;
  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值