C语言由浅入深理解指针

目录
  • 1. 相关概念
  • 2. 指针的定义方法
  • 3. 指针的分类
  • 4. 指针和变量的关系
  • 5. 指针与数组的关系
  • 6. 指针的运算

1. 相关概念

  • 操作系统给每个存储单元分配了一个编号,从ox00 00 00 00~0xff ff ff ff,这个编号称为地址,指针就是地址
  • 指针变量:即这个变量用来存放一个地址编号
  • 无论什么类型的地址,都是存储单元的变换,在32位平台下都是4个字节,即任何类型的指针变量都是4个字节大小,64位操作系统占8个字节。
  • 对应类型的指针变量,只能存放对应类型的地址。例如整型指针变量,只能存放整型变量的地址。
#include <stdio.h>
int main()
{
    char *a;
    short *b;
    int *c;
    long *d;
    float *e;
    double *f;
    printf("sizeof(a)=%d\n", sizeof(a));
    printf("sizeof(b)=%d\n", sizeof(b));
    printf("sizeof(c)=%d\n", sizeof(c));
    printf("sizeof(d)=%d\n", sizeof(d));
    printf("sizeof(e)=%d\n", sizeof(e));
    printf("sizeof(f)=%d\n", sizeof(f));
    return 0;
}

可见,我的操作系统是64位的。

为什么在64位系统中指针的大小是8,而32位的却是4?

64位系统,这个位数指的是CPU 里面的通用寄存器的数据宽度为64位,也就是说一个地址占二进制位数是64,所以:

sizeof(double *)==sizeof(int *)==sizeof(char *)==64/8==8

32位系统,同理,他的一个地址占32位二进制空间,sizeof(double *)==sizeof(int *)==sizeof(char *)==32/8==4

其实明白了两个系统的寻址原理就能明白,大体就是这个原因。地址跟系统有关,但是基本数据类型占的大小是由C语言本身决定。

2. 指针的定义方法

数据类型 *指针变量名

int p; // 定义了一个指针变量p 在定义指针变量的时候, 是用来修饰变量的,代表指针变量。

关于指针的运算符:

& 取地址 * 取值

#include <stdio.h>
int main()
{
    int a = 100;
    int *p; // 定义一个指针变量
    p = &a; // 给指针变量赋值
    printf("a = %d, %d\n", a, *p);  // *p 等价于变量 a
    return 0;
}

拓展:如果一行中定义多个指针变量,每个变量前面都要加*修饰

3. 指针的分类

  1. 字符指针
  2. 短整型指针
  3. 整型指针
  4. 长整型指针
  5. float型指针
  6. double型指针
  7. 函数指针
  8. 结构体指针
  9. 指针的指针
  10. 数组的指针

4. 指针和变量的关系

引用变量的方法:

1.直接通过变量的名称

2.通过*指针名称 引用

#include <stdio.h>
int main()
{
    int *p1, *p2, temp, a, b;
    p1 = &a;
    p2 = &b;
    printf("请输入a,b的值:\n");
    scanf("%d %d", p1, p2); // 和之前的scanf不同,这里直接用p1p2作为写入地址。
    temp = *p1;  // 用p1指向的变量a给temp赋值
    *p1 = *p2; // 用p2指向的变量b给p1指向的变量a赋值
    *p2 = temp;  // temp给p2指向的变量b赋值
    printf("a=%d b=%d\n", a, b);
    printf("*p1=%d,*p2=%d\n", *p1, *p2);
    return 0;
}

如果想让不同类型的指针相互赋值的时候,需要强制类型转换:

#include <stdio.h>
int main()
{
    int a = 0x1234, b = 0x5678;  // 4个字节
    char *p1, *p2;  // char类型只能保存一个字节
    printf("%#x  %#x\n", a, b);
    p1 = (char *)&a;  // 强制类型转换
    p2 = (char *)&b;
    printf("%#x  %#x\n", *p1, *p2);
    p1++;  // 指针向上移动
    p2++;
    printf("%#x  %#x\n", *p1, *p2);
    return 0;
}

5. 指针与数组的关系

指针保存的是数组第一个元素的地址

也可以通过*(p+2)=100给当前地址的下一个变量赋值

#include<stdio.h>
int main(){
    int a[5] = {0,1,2,3,4};
    int *p;
    p = a;
    // 指针指向数组a的第一个元素的首地址
    printf("a[2]=%d\n",a[2]);
    printf("p[2]=%d\n",p[2]);
    // *(a+n) <==> *(p+n) <==> a[n] <==> p[n]
    printf("*(p+2)%d\n",*(p+2));
    printf("*(a+2)%d\n",*(a+2));
    printf("p=%p\n",p);
    printf("p+2=%p\n",p+2);
    return 0;
}

6. 指针的运算

指针可以加一个整数,往下指几个它指向的变量,结果还是地址

#include <stdio.h>
void test1()
{
    int a[10];
    int *p, *q;
    p = a;
    q = p + 2;  // p q 间隔8个字节,意味着加一个整数最终移动的字节数与指针变量的类型也有关系
    printf("p=%p\n", p);
    printf("q=%p\n", q);
    return;
}
int main()
{
    test1();
    return 0;
}

  • 两个相同的指针可以比较大小

前提:指向同一个数组的元素

#include <stdio.h>
void test2()
{
    int a[10];
    int *p, *q;
    p = &a[1];
    q = &a[6];
    if (p < q)
    {
        printf("p < q\n");
    }
    else if (p > q)
    {
        printf("p > q\n");
    }
    else
    {
        printf("p = q\n");
    }
    return;
}
int main()
{
    //  test1();
    test2();
    return 0;
}

  • 两个同类型的指针可以做减法

前提:指向同一个数组元素,减法的结果是指针指向的中间有多少个元素

#include <stdio.h>
void test3()
{
    int a[10];
    int *p, *q;
    p = &a[0];
    q = &a[3];
    printf("%ld\n", q - p);
    return ;
}
int main()
{
    //  test1();
    //  test2();
    test3();
    return 0;
}

  • 两个相同类型的指针可以相互赋值
#include <stdio.h>
void test4()
{
    int a = 100;
    int *p, *q;
    p = &a;
    printf("a=%d %d\n", a, *p);
    q = p;
    printf("*q=%d\n", *q);
    *q = 999;
    printf("a=%d\n", a);
}
int main()
{
    //  test1();
    //  test2();
    //  test3();
    test4();
    return 0;
}

到此这篇关于C语言由浅入深理解指针的文章就介绍到这了,更多相关C语言指针内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 简单总结C语言中各种类型的指针的概念

    C语言中有很多关于指针的使用,指针也是C语言的灵魂所在,而且C语言中也有很多有关指针的概念,这里学习并总结了一些知道的概念.   常量指针: 首先它是一个指针,常量只是用来修饰指针的定语.其定义如下: char const * cp; char a='a'; 如何识别呢?根据右结合优先,先是*优先,所以这个cp变量是一个指针,然后是const修饰*,所以这是一个常量指针.即指向常量的指针. cp=&a; //正常语法 *cp=a; //错误语法,因为其指向的值是一个常量 指针常量: 首先它是一个

  • C语言超详细讲解指针的概念与使用

    目录 一.指针与一维数组 1. 指针与数组基础 2. 指针与数组 3. 一个思考 二.指针与字符串 三.指针和二维数组 1. 指针数组与数组指针 2. 指针数组 3. 数组指针 一.指针与一维数组 1. 指针与数组基础 先说明几点干货: 1. 数组是变量的集合,并且数组中的多个变量在内存空间上是连续存储的. 2. 数组名是数组的入口地址,同时也是首元素的地址,数组名是一个地址常量,不能更改. 3. 数组的指针是指数组在内存中的起始地址,数组元素的地址是指数组元素在内存中的其实地址. 对于第一点数

  • C语言由浅入深理解指针

    目录 1. 相关概念 2. 指针的定义方法 3. 指针的分类 4. 指针和变量的关系 5. 指针与数组的关系 6. 指针的运算 1. 相关概念 操作系统给每个存储单元分配了一个编号,从ox00 00 00 00~0xff ff ff ff,这个编号称为地址,指针就是地址 指针变量:即这个变量用来存放一个地址编号 无论什么类型的地址,都是存储单元的变换,在32位平台下都是4个字节,即任何类型的指针变量都是4个字节大小,64位操作系统占8个字节. 对应类型的指针变量,只能存放对应类型的地址.例如整型

  • C语言 从根本上理解指针

    目录 一.* 的意义 二.传值调用与传址调用 三.常量与指针 四.小结 一.* 的意义 在指针声明时,* 号表示所声明的变量为指针 在指针使用时,* 号表示取指针所指向的内存空间中的值 如下: int i = 0; int j = 0; int* p = &i; //指针声明 j = *p; //取值 变量 p 保存着变量 i 的内存地址,即:p <--> &i *p <--> i * 号类似一把钥匙,通过这把钥匙可以打开内存,读取内存中的值. 下面看一个指针的使用

  • C语言利用面试真题理解指针的使用

    目录 前言 笔试题一 笔试题二 笔试题三 笔试题四 笔试题五 笔试题六 笔试题七 笔试题八 前言 大家好~我又来了,今天给大家带来的是指针的几道笔试题,希望能够加强大家对指针知识的把握,指针就应该这样学! 笔试题一 #include<stdio.h> int main() { int a[5] = { 1 , 2 , 3 , 4 , 5 }; int* ptr = (int*) (&a + 1); printf("%d, %d", *(a + 1), *(ptr -

  • C语言由浅入深讲解文件的操作上篇

    目录 为什么使用文件 什么是文件 文件名 关于文件的一些概念 文件函数 fopen fclose 实例代码 绝对路径 文件的打开方式 文件操作流程 为什么使用文件 前面写的通讯录,增加人数退出程序后,数据就会消失.此时数据是存放在内存中,下次运行通讯录程序的时候,数据又得重新录入,如果使用这样的通讯录就很难受. 所以文件操作就应运而生.数据持久化的方法有两种:1.把数据存放在磁盘文件2.存放到数据库使用文件我们们可以将数据直接存放在电脑的硬盘上,做到了数据的持久化. 什么是文件 但是在程序设计中

  • C语言由浅入深讲解线程的定义

    目录 线程的概念 线程的创建 线程的终止 线程标识的比较 线程的取消 线程等待 线程分离 线程的概念 可以简单理解为一个正在独立运行的函数 注: 1.posix线程是一套标准吗,而不是实现 2.线程标识: phread_t,可能是整形也可能是结构体指针等 *简单介绍关于线程标识的函数* *pthread_equarl() ;判断两个线程标识是否相等**pthread_self():返回自身的线程标识* 线程的创建 pthread_creat(); int pthread_create( pthr

  • Go语言中的指针运算实例分析

    本文实例分析了Go语言中的指针运算方法.分享给大家供大家参考.具体分析如下: Go语言的语法上是不支持指针运算的,所有指针都在可控的一个范围内使用,没有C语言的*void然后随意转换指针类型这样的东西.最近在思考Go如何操作共享内存,共享内存就需要把指针转成不同类型或者对指针进行运算再获取数据. 这里对Go语言内置的unsafe模块做了一个实验,发现通过unsafe模块,Go语言一样可以做指针运算,只是比C的方式繁琐一些,但是理解上是一样的. 下面是实验代码: 复制代码 代码如下: packag

  • C语言中的指针以及二级指针代码详解

    很多初学者都对C中的指针很迷糊,希望这篇blog能帮助到大家: 1.什么是"指针": 在执行C程序的时候,由于我们的数据是存储在内存中的.所以对于C程序本身来说,如果想找到相应被调用的数据,就要知道存储该数据的内存地址是多少,换言之,C程序通过已知的内存地址到相应的内存位置存储数据. 这里简单说一下内存管理(对于初学者来说.为了避免专业术语引发的理解问题,下面的叙述尽量避免专业定义:),对于现代计算机系统来说,内存空间分为两个区域,一个是"数据区",一个是"

  • C语言玩转指针之指针的高阶玩法

    目录 前言 一.字符指针 二.指针数组和数组指针 1.指针数组 2.数组指针 2.1.数组指针是什么? 2.2.&数组名和数组名的区别 2.3.数组指针的使用 三.数组参数与指针参数 1.一维数组参数 2.二维数组参数 3.一级指针传参 4.二级指针传参 四.函数指针 五.函数指针数组 六.指向函数指针数组的指针 七.回调函数 总结 前言 指针第一篇,万人浏览: [C语言]玩转指针--关于指针,你需要掌握的基础知识! 指针的主题,我们在初级阶段的<指针>章节已经接触过了,我们知道了指针

  • C语言之初识指针

    指针是什么? 那到底什么是指针呢,其实指针和之前学习的变量基本相似,不过变量里面放的是一些值,而指针里面放的是它所指的地方的地址.在声明一个变量是,计算机就会为该变量预留一个位置,而指针所指☞的就是那个位置. 举个例子: int a = 10;//设置一个变量a的值为10 int *p = &a;//p这个指针里面就放的是a的地址 而&这个符号,就是取地址符,就像我们在使用scanf函数时  scanf("%d",&a); 这个a前面的&是一个意思,就是

  • C语言数组和指针,内存之间的关系

    首先论证一维数组和一级指针之前的关系,我们常常使用一级指针指针的方式访问一维数组,只有对内存的理解到位才能理解它们直接的关系. 1.数组名是数组的首地址 2.对数组名取地址得到的还是数组的首地址 3.数组的访问方式其实就是首地址+偏移的寻址访问 我们在程序中会定义很多变量,有基本类型和自定义类型在进行开发的时候我对内存的访问访问就是通过变量名赋值的方式读写内存但是如果你看到的直接变量的符号名你将不可能理解内存.每一种类型都有字节宽度,char 1字节 short 2字节 int 字节float

随机推荐