指针初识

  指针可以说是c语言从汇编那继承下来的!C语言中指针就跟汇编中的直接寻址,间接寻址等一样,去自直接操作内存;直接去操作内存,效率更高;

  指针是C语言中的精华,在C语言中很多地方都会用到指针(函数传参,函数返回值等);指针让程序员可以写出高的数据结构,编写出简洁,紧凑,高效的程序;

  所以要想熟练的使用C,指针是必不可少的;

  注意:在32位的操作系统中,不管定义的是什么类型的指针都是4字节;

1. 指针带来的一些符号的理解
  1. 星号* :
    (1)定义指针:*和前面的类型结合,定义一个该类型的指针(int *p;定义一个int类型的指针)
    (2)解引用:解引用时*p表示的是p所指向的变量;(p = &a;当操作*p时相当与操作变量a)
  2.取地址符&:
    (1)&a 表示变量a的内存地址;
    (2)取地址符使用时直接加在一个变量的前面,取地址符和变量重新构成一个新的符号,表示这个变量的内存地址(int a = 32; int *p =&a;//将a的地址赋值给p;当下次解引用p时,相当与操作变量a)

2. 指针定义并初始化,与指针定义然后赋值的区别
  1.指针定义并初始化:

1 int a = 32;
2 int *p = &a;

  2.指针定义然后赋值:

1 int a = 32;
2 int *p;
3 p = &a;

3. 野指针的问题
  1.野指针带来的危害:
    (1)野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)
    (2)野指针很可能运行时触发段错误(Sgmentation fault)
    (3)因为指针变量在定义时如果没有初始化,值是随机的。指针变量的值其实就是别的变量(指针所指向的那个变量的地址),也就意味着这个指针变量很可能指向该程序中的某一个变量的地址,当这时去解              引用这个指针时将会改变这个被指向的变量;可能导致程序发生未知的错误;

  2.怎么避免野指针    

    (1)野指针的错误来源就是指针在定义时没有初始化,也没有给赋值(也就是没有让指针指向一个可用的内存空间),然后就直接进行解引用;
    (2)明白了野指针的来源,解决方法就是:在指针的解引用之前,一起确保指针指向一个绝对可用的空间。
    (3)常规避免野指针的作法:
        1.定义指针时,同时初始化为NULL
        2.在指针使用之前,将其赋值绑定给一个可用的地址空间
        3.在指针被解引用之前,先去判断这个指针是不是NULL
        4.指针被解引用之后,将其赋值为NULL

 1 int *p = NULL;    //定义指针,并初始化为NULL
 2
 3 int a = 4;      //定义一个变量
 4
 5 p = &a;        //将a的地址与指针p绑定起来
 6
 7 if(NULL != p)    //指针解引用之前,判断指针是不是NULL,是不是有绑定有效的地址
 8 {
 9     *p = 10;       //指针p解引用
10 }
11
12 p = NULL;      //指针解引用后,将其赋值为NULL

    附件内容:为什么要将指针初始化为NULL?
      1.NULL的实质就是0,然后给指针赋初值NULL,其实就是让指针指向0地址处;
      2. 0地址处作为一个特殊的地址(我们认为指针指向0地址,就表明该指针没有被初始化,表明这是一个野指针);
      3. 0地址在一般的操作系统中都不可被访问,这也就表示当指针被指向0地址时,不会在随机的指向其它的地址,也就不会不知不觉的操作其它未知的内存地址;

4. const关键字与指针
  1. const修饰指针的4种形式
    1.const关键字,在C语言中用来修饰变量,表示这个变量是一个常量;
    2.const修饰指针的以下4种形式:

1       const int *p;    //表示p不是const,而p指向的变量是const(常量)
2       int const *p;    //表示p不是const,而p指向的变量是const(常量)
3         int * const p;    //表示p是const,而p指向的变量不是const(常量)
4       const int * const p;//表示p是const,而p指向的变量也是const(常量)

    3.关于指针变量的理解,主要涉及到2个变量:第一个是指针变量p本身,第二个是p指向的那个变量(*p)。一个const关键字只能修饰一个变量,所以弄清除这4个表达式的关键就是弄清
    楚const在表达式中修饰的是哪个变量;
      1.const int *p; //const修饰的是*p(也就是p所指向的那个变量(*p))
      2.int const *p; //const修饰的是*p(也就是p所指向的那个变量(*p))
      3.int * const p; //const修饰的是p(也就是p指针变量本身)
      4.const int * const p; //前面的const修饰的是*p,后面的const修饰的是p;

5. 理解数组中a, &a, &a[0], a[0]的区别;
  例如:int a[5];

  1.a表示的是数组名,a做左值时表示的是a[5]这个数组的整个内存空间(5*4=20字节);但是C语言中规定数组操作时要独立操作,不能整个数组一起操作,所以a不能做左值;a做右
  值时,表示数组首元素(也就是a[0])的首地址,a做右值时相当于&a[0](两者的数值是一样的);

  2.&a就是数组名a取地址,就是数组的地址;&a不能做左值(&a实质是一个常量,仅仅是表示这整个数组的首地址,不是变量所以不能赋值,也就不能做左值);&a做右值时,表示整个数组
  内存空间的首地址;在数值上与a,&a[0]是一样的;

  3.&a[0]表示的是数组首元素(a[0])的首地址([]的优先级高于&,所以a先和[]结合再去地址);&a[0]是不能做左值的,&a[0]是a[0]的首地址是一个常量;做为右值时,表示的是
  a[0]的首地址;

  4.a[0]表示数组的首元素;做左值时表示a[0]对应的连续4字节空间;做右值时表示的是a[0]对应内存空间中存放的值;

  总结:
    1.&a和a做右值时的区别:&a是整个数组的首地址,而a是数组首元素的首地址。这两个在数值上是相等的,但是意义不同,意义不同会导致他们在参与运算时有不同的表现;
    2.a和&a[0]做右值时意义和数组完全相等,完全可以互相替代;
    3.&a是常量,表示整个数组内存空间的首地址,不能做左值;
    4.a做左值代表整个数组所以空间,所以不能做左值;

参考内容:朱老师物联网大讲堂

时间: 2024-10-01 05:11:57

指针初识的相关文章

2.10一级指针初识

[注:自己从老师讲解出理解的,不对的地方望指正] [注:本程序验证是使用vs2013版] [刚学c的一句话:独学而无友,孤陋而寡闻] #include <stdio.h> #include <stdlib.h> #include <string.h> #pragma warning(disable:4996) int main(void){ /* 1.指针是一种数据类型,是指它指向的内存空间的数据类型. 2.初始化的指针是一个变量,是变量的话内存就需要给这个变量存放的地

C语言指针初识

定义指针变量 定义指针变量,在变量名前面加星号*,格式为: int a; datatype *pointname; int *p; p = &a; 或者 int a; datatype *pointname = value; int *p = &a; 定义指针变量时必须带*,给指针变量赋地址值时不能带*,等于一个地址即可改变指针指向. 1 //定义普通变量 2 float a = 99.5, b = 10.6; 3 char c = '@', d = '#'; 4 //定义指针变量 5 f

初识指针

指针,我理解就是保存另一个变量的地址的变量.例如int x,这个变量,它的内存地址可以用&x这个表达式得到. 如果要利用这个内存地址来处理x的话,可以利用*x来作为它的指针,*x就是存储x内存地址的变量.例如: 对*x进行操作: *x = 5  那么就把5这个值放到来这个指针指向的内存位置,也就是x变量.下面的代码用来获得数组的最大值. 1 #include <stdio.h> 2 3 void max(int list[], int len, int *x) // x means m

深入理解C指针之一:初识指针

简单来说,指针包含的就是内存地址.理解指针关键在于理解C的内存管理模式.C里面有三种内存: ①.静态全局内存(生命周期从程序开始到程序结束,全局变量作用域是全局,静态变量作用域在定义它们的函数内部): ②.自动内存(在函数内部声明的变量,在函数被调用时创建,作用域和生命周期都在函数内部): ③.动态内存(内存分配在堆上,根据需要释放,通过指针引用,作用域局限于引用的指针): 下面先来生命一个指针并打印其地址和值,这里p%指的是以十六进制的形式返回数据: #include <stdio.h> m

1.1 初识指针

指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址. 要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的 类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区.让我们分别说明. 先声明几个指针放着做例子: 例一: (1)int*ptr; (2)char*ptr; (3)int**ptr; (4)int(*ptr)[3]; (5)int*(*ptr)[4]; 1.指针的类型 从语法的角度看, 你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的

[002]初识指针

指针(pointer)与引用都实现了对其它对象的间接访问,但与引用不同的是,指针本身是一个对象,也无须在定义时赋初值.用*p的形式来定义指针. 1 int val, *p2; //val是int类型对象,p2是指向int对象的指针 由于指针存放的是对象的地址,所以要想获取该地址,需要使用取地址符(&). 1 int val = 1024; 2 int *pval = &val; //pval是指向变量val的指针 与引用类似,大多数情况下指针的类型都要与其指向的对象严格匹配. 未完.

初识git

初识git 1 安装git 最早Git是在Linux上开发的,很长一段时间内,Git也只能在Linux和Unix系统上跑.不过,慢慢地有人把它移植到了Windows上.现在,Git可以在Linux.Unix.Mac和Windows这几大平台上正常运行了. 要使用Git,第一步当然是安装Git了.根据你当前使用的平台来阅读下面的文字: 1.1 在Linux上安装Git 首先,你可以试着输入git,看看系统有没有安装Git: ``` $ git The program 'git' is curren

ARC - strong和weak指针

ARC指南1 - strong和weak指针 提示:本文中所说的"实例变量"即是"成员变量","局部变量"即是"本地变量" 一.简介 ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain.release.autorelease语句.你不再需要担心内存管理,因为编译器为你处理了一切 注意:ARC 是编译器特性,而不是 iOS 运行时特性(除了weak指针系统),它也不

Ajax—初识

看DRP的过程,重新学习了一遍Ajax,更深刻的体会到了Ajax所具有的魅力.Ajax是一种技术或者方法,更是一 种艺术.它让我们的程序以一种更完美的姿态呈现在用户面前.下面就让我们一起走进Ajax的世界. 简介 全名: AsynchronousJavaScript and XML. 工作原理: Ajax的工作原理相当于在用户和服务器之间加了-个中间层(AJAX引擎),使用户操作与服务器响应异步化.并不 是所有的用户请求都提交给服务器,像-些数据验证和数据处理等都交给Ajax引擎自己来做,只有确