设为首页 加入收藏

TOP

嵌入式linux之C语言高级专题指针详解1(一)
2016-08-20 00:03:26 】 浏览:626
Tags:嵌入式 linux 语言 高级 专题 指针 详解

1.1指针变量和普通变量的区别

指针的实质就是一个变量,其完整的名称是指针变量,与普通的变量没什么区别。指针存储的是地址,而普通变量存储的是数值。

1.2指针使用三部曲:定义指针变量、关联指针变量、解引用

1.2.1定义指针变量:类型名 * 指针变量

定义指针时的星号的位置不一样从而有三种定义:(1)int * a; (2)int* a;(3)int *a;

我编写了一下代码来验证以上的三种情况:

#include 
  
   

int main(void)
{
	int a=5;
	int *p1;
	int* p2;
	int * p3;
	p1 = &a;
	p2 = &a;
	p3 = &a;
	printf("*p1 = %d\n",*p1);
	printf("*p2 = %d\n",*p2);
	printf("*p3 = %d\n",*p3);
	return 0;
}

  

在linux系统中利用terminal中的gcc交叉编译工具来编译和运行c代码,运行结果如下图所示:

\

结论:三种定义的运行结果一样,故三种定义等价

1.2.2关联指针变量

关联指针变量的两种方法:(1)在定义指针时,初始化指针变量(2)指针变量= &变量

通过以上的两种方法,可以将指针指向应该访问的地方,如果没对指针进行关联,就访问指针指向地址中的变量,会导致系统出现不可预料的严重后果。

1.2.3解引用

星号在用于指针相关功能的时候有2种用法:第一种是指针定义时,*结合前面的类型用于表明要定义的指针的类型;第二种功能是指针解引用,解引用时*p表示p指向的变量本身

1.3指针中的一些符号的理解

1.3.1星号*

(1)C语言中*可以表示乘号,也可以表示指针符号。这两个用法是毫无关联的,只是恰好用了同一个符号而已。

(2)星号在用于指针相关功能的时候有2种用法:第一种是指针定义时,*结合前面的类型用于表明要定义的指针的类型;第二种功能是指针解引用,解引用时*p表示p指向的变量本身

1.3.2取地址符

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

1.3.3 NULL是什么?

NULL在C/C++中定义为:

#ifdef _cplusplus			// 定义这个符号就表示当前是C++环境
#define NULL 0				// 在C++中NULL就是0
#else
#define NULL (void *)0		// 在C中NULL是强制类型转换为void *的0
#endif

1.4左值与右值

(1)放在赋值运算符左边的就叫左值,右边的就叫右值。所以赋值操作其实就是:左值= 右值;

(2)当一个变量做左值时,编译器认为这个变量符号的真实含义是这个变量所对应的那个内存空间;当一个变量做右值时,编译器认为这个变量符号的真实含义是这个变量的值,也就是这个变量所对应的内存空间中存储的那个数。

(3)左值与右值的区别,就好象现实生活中“家”这个字的含义。譬如“我回家了”,这里面的家指的是你家的房子(类似于左值);但是说“家比事业重要”,这时候的家指的是家人(家人就是住在家所对应的那个房子里面的人,类似于右值)

1.5野指针问题

1.5.1野指针的相关概念

(1)因为指针变量在定义时如果未初始化,值也是随机的。指针变量的值其实就是别的变量(指针所指向的那个变量)的地址,所以意味着这个指针指向了一个地址是不确定的变量,这时候去解引用就是去访问这个地址不确定的变量,所以结果是不可知的。

(2)因为野指针指向地址是不可预知的,所以有3种情况:

第一种是指向不可访问(操作系统不允许访问的敏感地址,譬如内核空间)的地址,结果是触发段错误,这种算是最好的情况了;

第二种是指向一个可用的、而且没什么特别意义的空间(譬如我们曾经使用过但是已经不用的栈空间或堆空间),这时候程序运行不会出错,也不会对当前程序造成损害,这种情况下会掩盖你的程序错误,让你以为程序没问题,其实是有问题的;

第三种情况就是指向了一个可用的空间,而且这个空间其实在程序中正在被使用(譬如说是程序的一个变量x),那么野指针的解引用就会刚好修改这个变量x的值,导致这个变量莫名其妙的被改变,程序出现离奇的错误。一般最终都会导致程序崩溃,或者数据被损害。这种危害是最大的。

1.5.2避免野指针的技巧(很有价值的方法)

(1)野指针的错误来源就是指针定义了以后没有初始化,也没有赋值(总之就是指针没有明确的指向一个可用的内存空间),然后去解引用。故在指针的解引用之前,一定确保指针指向一个绝对可用的空间。

(2)常规的做法是:

第一点:定义指针时,同时初始化为NULL

第二点:在指针使用之前,将其赋值绑定给一个可用地址空间

第三点:在指针解引用之前,先去判断这个指针是不是NULL

第四点:指针使用完之后,将其赋值为NULL

#include 
  
   
int main(void)
{
int a;   
int *p = NULL;//第一点:定义指针时,同时初始化为NULL
*p = &a;    //第二点:在指针使用之前,将其赋值绑定给一个可用地址空间
if(NULL!=p)//第三点:在指针解引用之前,先去判断这个指针是不是NULL
{
	.....
	p = NULL; //第四点:指针使用完之后,将其赋值为NULL
}
return 0;

}

  

1.5.3 const关键字与指针

1. const修饰指针的4种形式

第一种:const int *p;

第二种:int const *p;

第三种:int * const p;

第四种:const int * const p;

指针变量涉及到2个变量:第一个是指针变量p本身,第二个是p指向的那个变量(*p)。一个const关键字只能修饰一个变量,所以弄清楚这4个表达式的关键就是搞清楚const放在某个位置是修饰谁的。

(1)const int *p 或者int const *p

p指向的变量是const常量

(2)int * const p 或者 const int * const p

p本身是const常量,p指向的变量也是const常量

1.6深入学习一下数组

1.6.1从内存角度来理解数组

(1)从内存角度讲,数组变量就是一次分配多个变量,而且这多个变量在内存中的存储单元是依次相连接的。

(2)我们分开定义多个变量(譬如int a, b, c, d;)和一次定义一个数组(int a[4]);这两种定义方法相同点是都定义了4个int型变量,而且这4个变量都是独立的单个使用的;不同点是单独定义时a、b、c、d在内存中的地址不一定相连,但是定义成数组后,数组中的4个元素地址肯定是依次相连的。

(3)数组中多个变量虽然必须单独访问,但是因为他们的地址彼此相连,因此很适合用指针来操作,因此数组和指针天生就叫纠结在一起。

1.6.2数组中几个关键符号(a a[0] &a &a[0])的理解

(1)a就是数组名。

la做左值时表示整个数组的所有空间,又因为C语言规定数组操作时要独立单个操作,不能整体操作数组,所以a不能做左值

la做右值表示数组首元素(数组的第0个元素,也就是a[0])的首地址(首地址就是起始地址,

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C语言基础 下一篇《C语言及程序设计》实践项目11 ..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目