C语言——初识指针

C语言——初识指针,第1张

C语言——初识指针

目录

1.指针是什么

2.与指针有关的运算符

3.指针的初始化

4.基本类型指针

5.指针和数组

6.多级指针

7.指针变量的运算


1.指针是什么

       从根本上看,指针(pointer)是一个值为内存地址的变量(或数据对象)。比如char类型变量的值为字符,int 类型变量的值是整数,指针变量的值是地址。例如:

int * p;//定义了一个指针变量p,p的类型为int *,p指向的地址为 int 类型

通俗来讲,指针就是地址,地址就是指针,不过要注意的是,虽然我们在平时会将指针变量简称为指针,但指针变量和指针是有所不同的,指针变量是存放地址的变量,也就是存放指针的变量。

2.与指针有关的运算符

1) *  (星号)

C语言中*可以表示乘号,也可以表示指针符号。这两个用法是毫无关联的,只是恰好用了同一个符号而已,星号在用于指针时有两种用法:

①指针定义时,*结合前面的类型用于表明要定义的指针的类型;

②指针解引用,解引用时*p表示p指向的变量本身。

int *p;//这是星号的第一种用法,定义了一个指针变量 P 
int *q ,*r;//当同时想定义两个或者多个指针时,也可以采用这样的语句
int i=5,j;
p = &i; //p保存了i的地址,p指向i
j = *p;//这是星号的第二种用法,把p指向的地址上的值赋给j,此时j=5 

2) & (取地址符)

取地址符使用时直接加在一个变量的前面,然后取地址符和变量加起来构成一个新的符号,这个符号表示这个变量的地址。

3.指针的初始化

指针初始化目的就是让指针知道指向那个地址。共有两种方式初始化指针:①在声明指针时便告诉指针指向地址;②不在声明指针的时候初始化,而是把地址直接赋值给指针变量。

注意:不可以在指针不清楚指向地址的情况下给指针赋值(但是char p=0或者p=NULL除外,该语句表示指针为空)。

①在声明指针时便告诉指针指向地址

#include 
int main (void)
{
	int i=5;
	int *p=&i;
	return  0;
}

②不在声明指针的时候初始化,而是把地址直接赋值给指针变量

#include 
int main (void)
{
	int i=5;
	int *p;
	p = &i;
	return  0;
}

③不可以在指针不清楚指向地址的情况下给指针赋值(错误)

#include 
int main (void)
{
	int i=5;
	int *p;
	*p = 5;
	return  0;
}
4.基本类型指针
int * p;
int i=5,j;
p = &i;//一个指针变量指向某个普通变量,则*指针变量等同于普通变量
       //对于此处即:*p=i=5 在所有出现 *p 或 i 的位置,两者可相互替换 
j = *p;//通过这几步,就可以将 i 的值 5 赋给 j       

1)内存泄漏

指针指向一个地址,也就是一个空间,如果只给指针分配空间,而未释放掉分配的空间,就会导致内存泄漏,导致内存越用越少;但如果,有多个指针同时指向同一个空间,而进行多次内存释放,就会使程序崩溃,导致无法运行。

2)空指针NULL

空指针就是值为0的内存逻辑地址,当对逻辑地址0(NULL)所代表的内存进行读写 *** 作时,程序就会崩溃。(返回值为指针的函数通常使用空指针作为失败时的返回值)

3)野指针

指向的位置不可知的指针。

出现原因:①声明指针后并未初始化

                  ②变量内存释放后,指针变量还保存着该变量的内存地址

5.指针和数组

一维数组名,是一个指针常量,他存放的是数组第一个元素的地址,例如:

#include 
int main (void)
{
	int a[5];
	
	printf ("%dn",&a[0]);//此处输出为a[0]的地址 
	printf ("%dn",a);//此处输出为数组名a的含义 
	
	return 0;
}

若两者输出结果相同,则说明一维数组名存放的是数组第一个元素的地址,运行程序输出结果如下: 

显然,两者输出结果相同,那么说明一维数组名存放的是数组第一个元素的地址。

指针和下标总存在着这样一个关系:如果 p 是一个指针变量,则 p[i] 永远等价于 *(p+i)

# include 
int main(void)
{
    int a[5] = { 1,2,3,4,5};
    int i;

    for( i = 0 ; i < 5 ; i++ )
	{
        printf("%d " , a[i]);
    }
    printf ("n");

    for(i = 0 ; i < 5 ; i++ )
	{
        printf("%d " , *(a+i));
    }

    return 0 ;
}

运行程序,输出结果如下:

 由此便可以证明该关系,p[i] 等价于 *(p+i)

注意区分:

int (*p[10])的含义是定义了一个数组,数组名为p,其中包含10个指针,指针指向整型类型数据

int (*p)[10]的含义是定义了一个指针,指针指向一个数组,数组中有10个元素,元素类型为整型

6.多级指针

如果一个指针指向的是另一个指针,我们就成他为二级指针,或者指向指针的指针。

那么如果指针指向的是一个二级指针,我们就称他为三级指针.......

那么对于多级指针,我们又该如何 *** 作呢?

#include 
int main (void)
{
	int i=10;
	int *p = &i;//定义了一个一级指针, p 存放 i 的地址 
	int **q = &p;//定义了一个二级指针,q 存放 p 的地址 
	int ***r = &q;//定义了一个三级指针,r 存放 q 的地址  r是int ***类型,所以r只能存放int **类型变量的地址
	
	//r = &p;//这样写是错误的 r是int ***类型,所以r只能存放int **类型变量的地址 不能存放int *类型变量的地址 
	
	printf ("%dn",i);
	printf ("%dn",*p);
	printf ("%dn",**q);
	printf ("%dn",***r);
	
	return 0;
}

i p q r 之间的关系可通过下图来理解

7.指针变量的运算

指针变量不能相加 不能相乘 不能相除 

如果两个指针变量指向同一块连续空间中不同的储存单元,则这两个指针变量可以相减。

    int i=5;
    int j=10;
    int *p = &i;
    int *q = &j;

此时 p-q 并没有实际意义,若将 p 和 q 放入同一个数组中,p-q 才会有实际意义。

#include 
int main (void)
{
	int a[5];
	int *p, *q;
	
	p = &a[1];
	q = &a[4];
	
	printf ("p和q所指向的单元相隔%d个单元n",q-p);
	
	return  0;
}

运行结果如下:

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5432563.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-11
下一篇 2022-12-11

发表评论

登录后才能评论

评论列表(0条)

保存