1、
①C语言中为什么指针那么重要呢
指针怎么用,指针和数组的关系,指针和指定地址调用某些地址写入数据的方法(一般是单片机编程中使用较多)
指针中野指针和内存泄露
函数指针和指针函数,函数数组,中断向量表正好就申请一个函数数组,之后调用中断好来调用函数。
void rt_hw_trap_irq()
typedef void (*rt_isr_handler_t)(int vector);
{
unsigned long ir;
rt_isr_handler_t isr_func;
ir = AINTC->GPIR & 0x7f; 中断服务地址表函数获取
isr_func = isr_table[ir];
isr_func(ir); 中断处理
AINTC->SICR = ir; 清
}
指针和数组的关系,指针对于数组的求地址取地址对应的变量(参考1-C语言深度解剖(131).pdf 第76页)
. 和 ->的使用区别
typedef struct
{
HOSTPACKETDESC *mTailBD;
HOSTPACKETDESC *mHeadBD;
U32 *mRegion0DescriptorAddress;
USBINSTANCE mUsbInst;
} CPPI41DMAINFO;
static CPPI41DMAINFO CppiInfo;
USBINSTANCE *UsbInstance = &CppiInfo.mUsbInst;
static CPPI41DMAINFO CppiInfo; //CPPI info结构体
CppiInfo.mHeadBD = NULL; //初始化CppiInfo结构体
CppiInfo.mTailBD = NULL;
CppiInfo.mTxCompletionq[0] = TX_COMPQ24; //TX完成队列
CppiInfo.mTxSubmitq[3][1] = TX_SUBMITQ23;
UsbInstance->mRxEndPoint[(EpInfo + EpNum)->mEndPoint].mChannel = (EpInfo + EpNum)->mEndPoint - 1;
UsbInstance->mRxEndPoint[(EpInfo + EpNum)->mEndPoint].mDmaMode = (EpInfo + EpNum)->mDmaMode;
C语言所有复杂的指针声明,都是由各种声明嵌套构成的。
要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内区。
指针的类型
从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。
这是指针本身所具有的类型。让我们看看例一中各个指针的类型:
(1)int*ptr;//指针的类型是int*
(2)char*ptr;//指针的类型是char*
(3)int**ptr;//指针的类型是int**
(4)int(*ptr)[3];//指针的类型是int(*)[3]
(5)int*(*ptr)[4];//指针的类型是int*(*)[4]
指针所指向的类型
当你通过指针来访问指针所指向的内存区时,指针所指向的类型决定了编译器将把那片内存区里的内容当做什么来看待。
从语法上看,你只须把指针声明语句中的指针名字和名字左边的指针声明符*去掉,剩下的就是指针所指向的类型。例如:
(1)int*ptr;//指针所指向的类型是int
(2)char*ptr;//指针所指向的的类型是char
(3)int**ptr;//指针所指向的的类型是int*
(4)int(*ptr)[3];//指针所指向的的类型是int()[3]
(5)int*(*ptr)[4];//指针所指向的的类型是int*()[4]
指针的值是指针本身存储的数值,这个值将被编译器当作一个地址,而不是一个一般的数值。
在32位程序里,所有类型的指针的值都是一个32位整数,因为32位程序里内存地址全都是32位长。
还有一点,指针在声明后其本身并不能表明是那种类型,因为其所在内存中存储的只是一个内存地址,
指针的加减运算都是编译器完成的,这点很重要。
②预编译宏使用#define #else #ifndef #endif
3.6,#pragma 预处理
在所有的预处理指令中,#pragma 指令可能是最复杂的了,它的作用是设定编译器的
状态或者是指示编译器完成一些特定的动作。#pragma 指令对每个编译器给出了一个方法,
在保持与C 和C ++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译
指示是机器或操作系统专有的,且对于每个编译器都是不同的。
其格式一般为:
#pragma para
其中para 为参数,下面来看一些常用的参数(参考1-C语言深度解剖(131).pdf 第六十八页)
③程序区域的知识,加载和运行域的概念
5.2,栈、堆和静态区
对于程序员,一般来说,我们可以简单的理解为内存分为三个部分:静态区,栈,堆。
很多书没有把把堆和栈解释清楚,导致初学者总是分不清楚。其实堆栈就是栈,而不是堆。
堆的英文是heap;栈的英文是stack,也翻译为堆栈。堆和栈都有自己的特性,这里先不做
讨论。再打个比方:一层教学楼,可能有外语教室,允许外语系学生和老师进入;还可能
有数学教师,允许数学系学生和老师进入;还可能有校长办公室,允许校长进入。同样,
内存也是这样,内存的三个部分,不是所有的东西都能存进去的。
静态区:保存自动全局变量和static 变量(包括static 全局和局部变量)。静态区的内容
在总个程序的生命周期内都存在,由编译器在编译的时候分配。
栈:保存局部变量。栈上的内容只在函数的范围内存在,当函数运行结束,这些内容
也会自动被销毁。其特点是效率高,但空间大小有限。
堆:由malloc 系列函数或new 操作符分配的内存。其生命周期由free 或delete 决定。
在没有释放之前一直存在,直到程序结束。其特点是使用灵活,空间比较大,但容易出错。(参考1-C语言深度解剖(131).pdf 第109页)
LR_IROM1 0xc0000000 0x1f400000 {
ER_IROM1 0xc0000000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$Sections)
.ANY (+RO)
}
RW_IRAM1 +0 { ; RW data
.ANY (+RW)
}
ER_ZI +0 { ; ZI data
.ANY (+ZI)
}
RW_RAM 0x80004000 0x0001c000 ; RAM段 (128-16)K
{
*(ram)
} 分散加载文件的使用
}
④变量函数相关
变量,全局和局部,外部和内部,static extern
结构体、枚举变量的使用,
1.14,struct 关键字
struct 是个神奇的关键字,它将一些相关联的数据打包成一个整体,方便使用。
在网络协议、通信控制、嵌入式系统、驱动开发等地方,我们经常要传送的不是简单
的字节流(char 型数组),而是多种数据组合起来的一个整体,其表现形式是一个结构体。
经验不足的开发人员往往将所有需要传送的内容依顺序保存在char 型数组中,通过指针偏
移的方法传送网络报文等信息。这样做编程复杂,易出错,而且一旦控制方式及通信协议
有所变化,程序就要进行非常细致的修改,非常容易出错。这个时候只需要一个结构体就
能搞定。平时我们要求函数的参数尽量不多于4 个,如果函数的参数多于4 个使用起来非
常容易出错(包括每个参数的意义和顺序都容易弄错),效率也会降低(与具体CPU 有关,ARM
芯片对于超过4 个参数的处理就有讲究,具体请参考相关资料)。这个时候,可以用结构体
压缩参数个数。
⑤⑥⑦⑧⑨⑩ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ
2、
3、
4、
5、
6、
7、
8、
9、