地址(Adress)

1.地址的作用

系统用来查找数据位置的依据,标识存储单元空间。

2.地址的表示

i>地址是一个整数值,(十六进制表示)每8bit一个址。

ii>编址。

1>按字节编址:每一个字节都有一个唯一的地址。

2>按字编址:双字=四个字节。

3.变量地址的表示

&+变量名

& 运算符

1> 单目运算符,结合性由右向左,优先级同 ! 、- 、~ 、前缀++、- -、* 、sizeof,可完整的表示变量的地址。

2>程序的每一个变量都有唯一的可标识的地址。

变量地址

1>按字节编址:一个变量单元占几个字节就占几个地址编号。

2>变量地址是变量第一个地址。

变量地址(决定第一个字节)+变量类型 可完整表示空间。

4.变量地址的分配

指针地址

5.地址的计算

1>计算过程

&变量名+(-)整数*sizeof(变量名)

2>*地址值:可表示一个单元的地址,但必须在表达式中体现改地址所对应的单元类型。

3>系统内真实计算

“ 段页式寻址 ”:段地址+段的偏移量+段内页地址+页的偏移量+页内偏移量。

指针

一级指针

一级指针:所有普通变量的第一个字节的地址都是一级指针,存放“一级指针“的变量为一级指针变量。

普通变量:凡是定义中没有 * 的都为普通变量。如:char a,int b。

一级指针类型

(1)类型结构:普通变量的类型+‘*’;

如: char a=‘a’;
char *p=&a; &a的类型为char * ,放&a的变量为 char * ,两边的类型不一样需强制转换。
指针地址
(2)理解char *
char :指针指向空间的解释方式。
*:它是一个指针。
(3)a/&a/p/*p/&p的含义。
char a=‘a’;
char *p=&a;
a:char型普通变量。
&a:a的指针,类型为char *.
p:char *指针变量。用来char *的存放。
*p:p中指针所指向的空间。p为char *,p解引时抵消一个‘’;
&p:变量p的指针,类型为char **。

#include<stdio.h>
int main(void)
{
 char a='a';
 char *p=&a;
 printf("a=%c &a=%d *p=%c &p=%d p=%d",a,&a,*p,&p,p);
 printf("\n"); 
}

结果区:

a=a &a=7011711 *p=a &p=7011696 p=7011711

多级指针之二级指针

对级指针:指针变量也是变量,所以指针变量的每个字节是有地址的,那么“指针变量”第一个字节的地址就是多级指针。指针变量的指针就是多级指针。在多级指针中*的个数代表指针的级数。

二级指针:一级变量指针的指针为二级指针,存放二级指针的变量为二级指针变量。

(1)类型结构:一级指针类型+ *;
如:int a=100;
int *p1=&a;
int **p=&p1;
(32位系统中)
指针地址
&p1:其类型为 int **,放&p1的变量p2自然 也是int **;
int **:int *:指针指向空间的解释方式。
*:指针。
(2)a/p1/*p1/&p1/p2/*p2/**p2/&p2各自的含义。
int a=100;
int *p1=&a;
int **p2=&p1;
a:int 型变量。
p1:int *指针变量,用于存放int *的指针。
*p1:p1中指针所指向的空间。
&p1:一级指针变量p1的指针为int **的二级指针。
p2:int **指针变量,用来存放int **的二级指针。
p2:一级解引用,代表的是p2指针中所指向的空间。
**p2:二级解引用,代表p2所指向的p1所指向的空间,就是a的空间。
**p2------>
(*p2)------->*p1----------->a;
&p2:二级指针p2的指针,类型为int **.


#include<stdio.h>
int main(void)
{
 int a=100;
 int *p1=&a;
 int **p2=&p1;
 printf("a=%d\tp1=%d\t*p1=%d\t&p1=%d\n*p2=%d\t**p2=%d\t&p2=%d",a,p1,*p1,&p1,*p2,**p2,&p2);
}

结果如下:


a=100   p1=7011708      *p1=100 &p1=7011696
*p2=7011708     **p2=100        &p2=7011688

野指针

概念::指向内存被释放的内存或者没有访问权限的内存的指针(非法访问)。野指针指向一个不确定的地址空间,或者指向的是一个确定的地址空间的,但引用空间的结果却是不可预知的。
与空指针不同,野指针无法通过简单地判断是否为 NULL避免,而只能通过养成良好的编程习惯来尽力减少。对野指针进行操作很容易造成程序错误。

造成原因:
1、指针定义时未被初始化:指针在被定义的时候,如果程序不对其进行初始化的话,它会指向随机区域,因为任何指针变量(除了static修饰的指针变量)在被定义的时候是不会被置空的,它的默认值是随机的。
2、指针被释放时没有被置空:我们在用malloc开辟内存空间时,要检查返回值是否为空,如果为空,则开辟失败;如果不为空,则指针指向的是开辟的内存空间的首地址。指针指向的内存空间在用free()或者delete(注意delete只是一个操作符,而free()是一个函数)释放后,如果程序员没有对其置空或者其他的赋值操作,就会使其成为一个野指针。
3、指针操作超越变量作用域:不要返回指向栈内存的指针或引用,因为栈内存在函数结束的时候会被释放


#include <stdio.h>

//这就是一种错误的写法
int main(void)
{
    int *p = NULL;
    p = (int *)malloc(4);
    
    //释放P所指向的内存空间,但指针变量p仍然留在栈中,成为了野指针
    if (p != NULL)
    {
        free(p);
    }
    
    if (p != NULL)
    {
        free(p);
    }

}

正确的写法:


#include <stdio.h>
//指针变量和指针所指向的内存变量是两个不同的概念
//使用动态内存分为三步
//1.定义时,将指针为定义NULL
//2.释放内存时,把指针变量重新赋值或者NULL
//3.释放内存后,把指针变量赋值为NULL
int main()
{
    int *p = NULL;
    p = (int *)malloc(4);
    
    //这才是正确的写法
    if (p != NULL)
    {
        free(p);//释放P所指向的内存空间,但指针变量p仍然留在栈中,成为了野指针
        p = NULL;//释放野指针
    }

    return 0;
}

相关文章: