初学者的指针学习笔记(1)

1.内存和地址

1.1内存

像学生宿舍一样,被分成许多个房间,每个房间都有自己的房号,每个房间能住8个学生

内存被分成许多个单元(小为1Byte),每个单元都有自己的编号,每个单元里能住8个小比特(bite)

c语言中,指针就是该单元内存的编号也就是地址,我们可以通过指针快速找到我们要访问的内存

1.2编址

计算机中的内存编址,是通过硬件设计来完成的,也就是说他被做出来的时候各个内存单元的地址就已经确定了

计算机中硬件之间数据的传递依赖3条“线”:

数据总线:用来传输数据

控制总线:控制数据的读(read)和写(write)

地址总线:提供需要传输的数据的内存地址

32位的计算机有32根地址总线,一根总线可以表示2个含义(有脉冲:1和无脉冲0)

32根则能表示2的32次方个含义,每一个含义表示一种地址。

2.指针变量和地址

2.1取地址操作符(&)

&取出的是较小的字节地址

比如创建一个整型变量a,&a取的是该整型所占据的4个字节中位最的那个字节内存地址

 初学者的指针学习笔记(1)_第1张图片

取出最小字节地址后,我们顺藤摸瓜也能访问到整个a所占据的内存数据。

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

2.2.1指针变量(用来存放指针的变量)

指针变量也是变量,用来存地址,被存到指针变量的值都会被理解为地址。

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

2.2.2指针的类型

pa的类型是int*,怎么理解?

*  说明pa是指针变量,int说明指针指向的是整型类的对象

以此类推,char类型的变量需要放在什么类型的指针变量中呢

2.2.3解引用操作符*(将取出来的地址用起来)

#include 
int main()
{
   int a = 100;
    int* pa = &a;
    *pa = 0;
    return 0;
}

这里*pa其实就是a变量了,(通过解pa中存放的地址,找到指向的空间)

在这里,这一步看似多余,但是当代码复杂起来之后,解指针的运用可以使代码更加灵活

2.3指针变量的大小

由上文知,32位机器由32个地址总线,我们把每一根转化成数字信号0或者1之后,32个总线组成的一个二进制序列看做一个地址,那么一个地址就是32个比特位,需要4个字节才能储存。

64位同理,需要8个字节。

那么我们就可以知道在同一个平台,指针变量的大小相同。

初学者的指针学习笔记(1)_第2张图片

3.指针变量类型的意义

3.1指针的解引用

代码1

#include 
int main()
{
    int n = 0x11223344;
    int *pi = &n;
    *pi = 0;
    return;
}

代码2 

#include 
int main()
{
    int n = 0x11223344;
    char *pc = (char *)&n;
    *pc = 0;
    return 0;
}
调试我们可以看到,代码1会将n的4个字节全部改为0,但是代码2只是将n的第⼀个字节改为0。

结论:指针的类型决定了,对指针解引⽤的时候有多⼤的权限⼀次能操作⼏个字节)。
⽐如: char* 的指针解引⽤就只能访问⼀个字节,⽽ int* 的指针的解引⽤就能访问四个字节。

3.2指针+-整数

#include 
int main()
{
    int n = 10;
    char *pc = (char*)&n;
    int *pi = &n;
    printf("%p\n", &n);
    printf("%p\n", pc);
    printf("%p\n", pc+1);
    printf("%p\n", pi);
    printf("%p\n", pi+1);
    return 0;
}

 初学者的指针学习笔记(1)_第3张图片

结论:指针的类型决定了指针向前或向后走一步有多大 ,如这边char*类型的指针一次走1个字节单位,而int*类型一次走4个字节。

3.3void*指针(泛指针)

即无具体类型的指针,这种指针可以接受任意类型地址,但是不能直接进行加减整数和解引用的运算

⼀般 void* 类型的指针是使⽤在函数参数的部分,⽤来接收不同类型数据的地址,这样的设计可以
实现泛型编程的效果。

4指针运算

4.1指针加减整数

以数组来举例,数组名就是首地址

#include 
//指针+- 整数
int main()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    int *p = &arr[0];//数组名就是首地址,这里&arr[0]可以改成arr
    int i = 0;
    int sz = sizeof(arr)/sizeof(arr[0]);
    for(i = 0; i < sz; i++)
    {
    printf("%d ", *(p + i));//p+i 这⾥就是指针+整数
    }
return 0;
}

该代码可以实现依次打印数组元素

4.2指针-指针

前提:两个指针指向同一空间—>每一次跳的距离相同

//指针-指针
#include 
int my_strlen(char *s)
{
    char *p = s;
    while(*p != '\0' )//\0的Ascll码值是0,括号里可以写成*p
    p++;
    return p-s;
}
    int main()
{
    printf("%d\n", my_strlen("abc"));
    return 0;
}

打印的结果时3,指针-指针得到的是两个地址间的元素个数

4.3指针关系运算

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

你可能感兴趣的:(学习,笔记)