Linux下C语言嵌入式笔记(一)

*基本位操作符:与、或、异或、非(取反)、左移、右移

  1. 位运算只能对整数;
  2. 左移运算符<<的移动位数>=类型长度的时候,在GCC环境下编译会有警告,实际移动位数为:左移位数%8。如int i = 1; i = i << 33; ===>i = 2 //i 左移33位,超过类型长度,则移动 33%8 = 1位
  3. 左移时总是移位和补零(逻辑左移),右移时无符号数是移位和补零,有符号数大多数是移位和补最左边的位;
  4. 未运算符的运算优先级较低;

位操作符的使用:
位与运算&:
特定数据段清零;
保留数据区的特定位;
判断奇偶:if(a&1==1) 来判断奇数;
位或运算符|
对数据的某几位置0或1
位异或^
特定值取反;
数值交换:
a = a^b;
b=b^a;
a=a^b;
位非~
对数据变换符号,只需要取非后加1;
位左移<<
数据扩大,溢出后舍去;
位右移 >>
实现除以2的整除运算(可以提高程序运行效率
);
求绝对值:
int i = a >> 31;
return i == 0 ? a : a + 1);
or
int i = a>>31;
return ((a^1)-i);

嵌入式开发中常用的位运算
将寄存器按指定位置1:GPXX |= (1<<7) |(1<<5);
将寄存器的指定位置0:GPXX &= ~(1<<n);
i &= ~(0x1F<<12); //清除bit12-17
取出bit7-17: a &= (0x7FF<<7);//(差别在于一个~)

C语言常见指针类型分析

int p;

这是一个普通的整型变量

int *p;

首先从P处开始,先与*结合,所以说明P是一个指针,然后再与int结合,说明指针所指向的内容的类型为int 型.所以 P是一个返回整型数据的指针

int p[3];

首先从P处开始,先与[]结合,说明P 是一个数组,然后与int结合,说明数组里的元素是整型的,所以 P是一个由整型数据组成的数组 

int *p[3];

首先从P处开始,先与[]结合,因为其优先级比*高,所以P是一个数组,然后再与*结合,说明数组里的元素是指针类型,然后再与 int结合,说明指针所指向的内容的类型是整型的,所以是一个由返回整型数据的指针所组成的数组 

int (*p)[3];

首先从P处开始,先与*结合,说明P是一个指针然后再与[]结合(与"()"这步可以忽略,只是为了改变优先级),说明指针所指向的内容是一个数组,然后再与int 结合,说明数组里的元素是整型的.所以P是一个指向由整型数据组成的数组的指针 

int **p;

首先从 P开始,先与*结合,说明P是一个指针,然后再与*结合,说明指针所指向的元素是指针,然后再与 int结合,说明该指针所指向的元素是整型数据. 所以P是一个返回指向整型数据的指针的指针 

int p(int);

从P处起,先与()结合,说明P是一个函数,然后进入()里分析,说明该函数有一个整型变量的参数然后再与外面的int 结合,说明函数的返回值是一个整型数据.所以P是一个有整型参数且返回类型为整型的函数 

int (*p)(int);

从P处开始,先与指针结合,说明P是一个指针,然后与()结合,说明指针指向的是一个函数,然后再与()里的int 结合,说明函数有一个int 型的参数,再与最外层的int 结合,说明函数的返回类型是整型,所以P是一个指向有一个整型参数且返回类型为整型的函数的指针 

int *(*p(int))[3];

从 P开始,先与()结合,说明P是一个函数,然后进入()里面,与int结合,说明函数有一个整型变量参数,然后再与外面的*结合,说明函数返回的是一个指针,,然后到最外面一层,先与[]结合,说明返回的指针指向的是一个数组,然后再与*结合,说明数组里的元素是指针,然后再与int 结合,说明指针指向的内容是整型数据.所以P是一个参数为一个整数且返回一个指向由整型指针变量组成的数组的指针变量的函数。

指针分析

指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。 要搞清一个指针需要搞清指针的四方面的内容:指针的类型、指针所指向的类型、指针的值或者叫指针所指向的内存区、指针本身所占据的内存区。

A、指针的类型

把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型
B、指针所指向的类型

把指针声明语句中的指针名字和名字左边的指针声明符*去掉,剩下的就是指针所指向的类型(在指针的算术运算中,指针所指向的类型有很大的作用)
C、指针所指向的内存区

指针变量定义之后必须赋值才能使用,指针所指向的内存区从指针的值所代表的那个内存地址开始,长度为sizeof(指针所指向的类型)的一片内存区。一个变量指针指向了某块内存区域,就相当于说该指针变量的值是这块内存区域的首地址。如果指针变量指向的内存区未初始化,则该内存区保存的是垃圾数据。如同变量定义之后不赋值就会是垃圾值一样,指针定义后也必须赋值指定合法内存地址,否则解引用将会出错(段错误)
D、指针本身所占据的内存区

用函数sizeof(指针的类型)可以测出指针本身所占据的内存区(在 32位平台里,指针本身占据了 4个字节的长度) 。

const与指针
const是一个C语言(ANSI C)的关键字,具有着举足轻重的地位。它限定一个变量不允许被改变,产生静态作用。使用const在一定程度上可以提高程序的安全性和可靠性。另外,在观看别人代码的时候,清晰理解const所起的作用,对理解对方的程序也有一定帮助。另外CONST在其它编程语言中也有出现,例如Pascal、C++、PHP5、B#.net、HC08 C、C#等。

const int *p;指针p为变量,指针指向的内存空间存储的是常量

int const *p;指针p为变量,指针指向的内存空间存储的是常量

int * cosnt p;指针是常量,指针指向的内存空间存储的是变量

const int * const p;指针是常量,指针指向的内存空间存储的是常量

野指针

野指针是指向的地址不可预知的指针。野指针容易触发运行时段错误。一般来说,指针定义后如果没有赋值就使用就是一个野指针,指向的内存地址空间是不确定的。避免野指针的一般做法:

A、定义指针时初始化为NULL

B、解引用指针前将指针赋值

C、解引用指针前检查指针是否是NULL

D、指针使用完毕后赋值NULL

指针运算符

A、取地址运算符&
   取地址运算符&是单目运算符,其结合性为自右至左,其功能是取变量的地址。&a的运算结果是一个指针,指针的类型是a的类型加个*,指针所指向的类型是a的类型,指针所指向的地址,那就是a的地址。

B、取内容运算符*
   取内容运算符是单目运算符,其结合性为自右至左,用来表示指针变量所指的变量。在运算符之后跟的变量必须是指针变量。需要注意的是指针运算符和指针变量说明中的指针说明符* 不是一回事。在指针变量说明中,“”是类型说明符,表示其后的变量是指针类型。而表达式中出现的“”则是一个运算符,用以表示指针变量所指的变量。

两指针变量进行关系运算

指向同一数组的两指针变量进行关系运算可表示它们所指数组元素之间的关系。例如:
pf1==pf2表示pf1和pf2指向同一数组元素
pf1>pf2表示pf1处于高地址位置
pf1<pf2表示pf2处于低地址位置

指针变量还可以与0比较。设p为指针变量,则p==0表明p是空指针,它不指向任何变量;p!=0表示p不是空指针。空指针是由对指针变量赋予0值而得到的。例如: #define NULL 0int *p=NULL; 对指针变量赋0值和不赋值是不同的。指针变量未赋值时,可以是任意值,是不能使用的。否则将造成意外错误。而指针变量赋0值后,则可以使用,只是它不指向具体的变量而已。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值