浅谈指针(1)

简介: 浅谈指针(1)

前言

目的:快速了解指针基础

一个内存单元一个字节,一个字节8个bit位

究竟该如何理解编址


们今天关⼼⼀组线,叫做地址总线。

我们可以简单理解,32位机器有32根地址总线,

每根线只有两态,表⽰0,1【电脉冲有⽆】,那么

⼀根线,就能表⽰2种含义,2根线就能表⽰4种含

义,依次类推。32根地址线,就能表⽰2^32种含

义,每⼀种含义都代表⼀个地址。

地址信息被下达给内存,在内存上,就可以找到

该地址对应的数据,将数据在通过数据总线传⼊

CPU内寄存器。


1. 内存与指针关系

内存单元的编号 == 地址 == 指针


c513823f266942819fe7192e8b395d9e.png

2. 指针变量和地址

2.1 操作符(&)-取地址操作符

那我们如何能得到a的地址呢?


#include <stdio.h>
int main()
{
  int a = 10;
  //&a取出a的地址
  printf("%p\n", &a);//%p是用来打印地址的
 return 0;
}

b084d4c086d947bd986ff4a2fde8ee7a.png


2.2 指针变量和解引⽤操作符(*)

#include <stdio.h>
int main()
{
  int a = 10;
    int* pa = &a;//取出a的地址并存储到指针变量pa中
    return 0;
 }


*p是指针变量内的值,*p是某个具体的值(是指针变量的内容),p是指针变量是用来存放地址的

改变变量的值操作如下:


int a = 10;
  int* p = &a
  *p = 20;/


相当于


2e4c0fab68a74913bd254b11398f381c.png

3 .指针变量的⼤⼩

32位机器假设有32根地址总线,每根地址线出来的电信号转换成数字信号后是1或者0,那我们把32根地址线产⽣的2进制序列当做⼀个地址,那么⼀个地址就是32个bit位,需要4个字节才能存储。


同理64位机器,假设有64根地址线,⼀个地址就是64个⼆进制位组成的⼆进制序列,存储起来就需要

8个字节的空间,指针变的⼤⼩就是8个字节。

X86环境输出结果:


84cd8f7755a74f958a5bd833888209e9.pngx64环境下输出结果:

c0e982e0417342f89f80dd3ad2d4a3fe.png


结论:

• 32位平台下地址是32个bit位,指针变量⼤⼩是4个字节

• 64位平台下地址是64个bit位,指针变量⼤⼩是8个字节

• 注意指针变量的⼤⼩和类型是⽆关的,只要指针类型的变量,在相同的平台下,⼤⼩都是相同的,所以说*p的大小可以比较,指针变量p不可以比较

4.指针变量类型的意义

a6d6e3994fa74240b756470494ea2d8a.png

831cbd705fd143298547a42891f26ce4.png

调试我们可以看到,代码1会将n的4个字节全部改为0,但是代码2只是将n的第⼀个字节改为0。

结论:指针的类型决定了,对指针解引⽤的时候有多⼤的权限(⼀次能操作⼏个字节)。

⽐如: char* 的指针解引⽤就只能访问⼀个字节,⽽ int* 的指针的解引⽤就能访问四个字节。


5.const修饰指针

• const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。但是指针变量本⾝的内容可变。

• const如果放在*的右边,修饰的是指针变量本⾝,保证了指针变量的内容不能修改,但是指针指向的内容,可以通过指针改变。

案例:


include <stdio.h>
int main()
{
  int m = 0;
  m = 20;//m是可以修改的
  const int n = 0;
  n = 20;//n是不能被修改的
 return 0;
}


上述代码中n是不能被修改的,其实n本质是变量,只不过被const修饰后,在语法上加了限制,只要我们在代码中对n就⾏修改,就不符合语法规则,就报错,致使没法直接修改n。


但是如果我们绕过n,使⽤n的地址,去修改n就能做到了,虽然这样做是在打破语法规则,如:


#include <stdio.h>
int main()
{
  const int n = 0;
  printf("n = %d\n", n);
  int*p = &n;
  *p = 20;
  printf("n = %d\n", n);
  return 0;
}


输出结果:

bf8e605ef3a04373b1712d940f8104a8.png


6. 野指针

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


成因:

1 . 指针未初始化:局部变量指针未初始化,默认为随机值,占用其他变量内存。

2. 指针越界访问:当指针指向的范围超出数组arr的范围时,p就是野指针。

3. 指针指向的空间释放:创建函数使用完后销毁。


如何规避野指针:

1 . 指针初始化:如果不知道指针应该指向哪⾥,可以给指针赋值NULL.如:


int*p2 = NULL;


2 . ⼩⼼指针越界:序向内存申请了哪些空间,通过指针也就只能访问哪些空间

3 . 指针变量不再使⽤时,及时置NULL,指针使⽤之前检查有效性。

4 . 避免返回局部变量的地址


7. 指针运算

指针的基本运算有三种,分别是:

• 指针± 整数

• 指针-指针

• 指针的关系运算


7.1 指针± 整数

因为数组在内存中是连续存放的,只要知道第⼀个元素的地址,顺藤摸⽠就能找到后⾯的所有元素.

案例:


#include <stdio.h>
//指针+- 整数
int main()
{
  int arr[10] = {1,2,3,4,5,6,7,8,9,10};
  int *p = &arr[0];
  int i = 0;
  int sz = sizeof(arr)/sizeof(arr[0]);
  for(i=0; i<sz; i++){
    printf("%d ", *(p+i));//p+i 这⾥就是指针+整数
  }
 return 0;
}


7.2 指针-指针


//指针-指针
#include <stdio.h>
int my_strlen(char *s)
{
  char *p = s;
  while(*p != '\0' )
  p++;
  return p-s;
}
int main()
{
  printf("%d\n", my_strlen("abc"));
  return 0;
}


指针-指针在数组中表示两个指针的之间的元素个数

7.3 指针的关系运算


/

/指针的关系运算
#include <stdio.h>
int main()
{
  int arr[10] = {1,2,3,4,5,6,7,8,9,10};
  int *p = &arr[0];
  int i = 0;
  int sz = sizeof(arr)/sizeof(arr[0]);
  while(p<arr+sz) //指针的⼤⼩⽐较
  {
    printf("%d ", *p);
    p++;
  }
 return 0;
}


相关文章
|
7月前
|
存储 C语言
指针详解(3)
指针详解(3)
|
2月前
|
编译器
指针初步讲解(下)
指针初步讲解(下)
37 2
|
7月前
|
存储 程序员 C++
c++指针
c++指针
38 1
|
7月前
|
存储 C语言
深入理解指针(1)
深入理解指针(1)
48 2
|
7月前
|
存储 C语言
c 指针
c 指针
47 0
|
7月前
|
存储 C++
C++指针
C++指针
|
7月前
|
存储
什么是指针?
什么是指针。
51 1
|
7月前
|
存储 C语言 C++
指针是什么
指针是什么
46 0
|
7月前
指针(3)
指针(3)
30 0
|
Perl
C指针(详解)
C指针(详解)
179 0