1:宏函数的实现
#definereadl(addr) (*(volatile unsigned int*)(addr))
#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b)):
宏函数里也可以定义变量
#define readb(addr) \
({ unsigned char __v =(*(volatile unsigned char *) (addr)); __v; }) /* \后面就是一个回车键,宏定义就是字符串替换*/
#define readw(addr) \
({ unsigned short__v = (*(volatile unsigned short *) (addr)); __v; })
局部变量的合法定义位置,依赖于编译器遵循的C规范版本:
1、仅支持C89规范的编译器,只支持在作用域起始部分定义变量。
2、支持C99或者部分支持C99的编译器:局部变量可以定义在任何位置
2:寄存器结构体的地址转化
#defineS3C24X0_CLOCK_POWER_BASE 0x4C000000
structs3c24x0_clock_power {
u32 LOCKTIME;
u32 MPLLCON;
u32 UPLLCON;
u32 CLKCON;
u32 CLKSLOW;
u32 CLKDIVN;
#if defined (CONFIG_S3C2440)
u32 CAMDIVN;
#endif
};
staticinline struct s3c24x0_clock_power *s3c24x0_get_base_clock_power(void)
{
return (struct s3c24x0_clock_power *)S3C24X0_CLOCK_POWER_BASE;/*将这一块内存转化为结构体类型*/
}
structs3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
3:代码屏蔽
#if0 //这段代码屏蔽掉
unsigned long cpu_clk; /* cpu频率*/
unsigned long bus_clk;/*总线频率*/
phys_size_t ram_size; /* RAM大小设置,64M*/
unsigned long reset_status; /* 重新设置状态地址*/
#endif
4:条件编译
flash_info[i].flash_id=
#if defined(CONFIG_AMD_LV400)
//include/flash.h中对flash的MANUFACT,VENDMASK,TYPEMASK有定义,主要是flash的ID
(AMD_MANUFACT & FLASH_VENDMASK) |
(AMD_ID_LV400B & FLASH_TYPEMASK);
#elif defined(CONFIG_AMD_LV800)
(AMD_MANUFACT & FLASH_VENDMASK) |
(AMD_ID_LV800B & FLASH_TYPEMASK);
#else
#error "Unknown flash configured"
#endif
5:NULL空的定义
空指针:
#ifndef NULL
#defineNULL ((void*) 0)
#endif /*NULL*/
空值:
#ifndefNULL
#define NULL 0
#endif
6:带路径的头文件包含
board.c
#include "../drivers/net/smc91111.h"
..是表示当前board.c源文件所在目录的上层目录
.表示当前board.c源文件所在的当前目录
例子中board.c完整路径: D:\ouyangLinux\uboot sourceinsight工程\u-boot-2010.03-embedclub-201111\u-boot-2010.03\lib_arm\board.c
smc91111.h完整路径:D:\ouyangLinux\ubootsourceinsight工程\u-boot-2010.03-embedclub-201111\u-boot-2010.03\drivers\net\smc91111.h
注意wen7和Linux的路径斜杠方向相反,很容易记反,打开计算机的搜索路径就知道斜杠方向,Linux方向就是烦的
7:如何给数组整体赋值
在C语言中是没有整体给数组赋值的函数
我们只能通过内存操作来一个一个字节的给数组的成员全部赋值,所以一般我们是对一个数组进行整体清零的操作,而不能通过内存操作函数来实现给数组整体赋一个非零的值
int i , hash[256];
memset(hash , 0 , sizeof(hash));
8:函数参数不能传递整个数组,只能传递数组的首地址,至于数组的内存的尾地址在哪里?传递的数组有多少个数组成员?一种方法是数组末尾成员用NULL或‘\0’等填充这个成员,另一种方法是再多传递一 个参数,指明数组有几个数组成员。
函数参数如何传递结构体?其实和传递int一样,会在函数内部定义一个局部变量,然后将它复制参数。所以传递结构体时我们也经常用指针方式传递。
9:&&条件的注意
//dev是在内核进行驱动和设备匹配时得到的设备的结构体, type是我们要取哪一种类型的资源,num是要取这种类型资源的第几个,
struct resource*platform_get_resource(struct platform_device *dev,
unsigned int type, unsigned int num)
{
inti;
for(i = 0; i < dev->num_resources; i++) {
structresource *r = &dev->resource[i];
if(type == resource_type(r) && num-- == 0)
returnr;//注意只有在资源类型匹配时,后面的语句才会执行,例如取这种资源类型type的第一个资源,则num--==0立刻满足条件,这///里是后减减,如果取第一个资源,则1!=0,下次再次遍历到这个资源类型是0--==0满足条件,就可以取出这个资源了
}
returnNULL;
}
10:结束数组遍历的方法:循环数组最后一个元素的初始化,数组最后一个元素为空或为-1:全身上下都是零
#include <stdio.h>
struct test{
int a;
char b;
};
struct test array[]={
[0] = {0,0},
{1,2},
{3,4},
{},//c语言语法会自动填零
};
int array2[4]={
1,2,3,//c语言语法会自动填零
};
char *str1="12345";
char *str2="67890";
struct str{
char *string;
};
struct str strarray[]={
[0]={str1},
{str2},
{} //c语言语法会自动填零
};
int main(void)
{
printf("/*************知道数组大小来结束遍历数组****************/\n");
int i=0;
for(;i<4;i++)
{
printf("array[%d]:a=%d,b=%d\n",i,array[i].a,array[i].b) ;
}
i=0;
for(;i<4;i++)
{
printf("array2[%d]:%d\n",i,array2[i]) ;
}
printf("/*************用数组最后一个元素来结束遍历数组****************/\n");
i=0;
while(array2[i])
{
printf("array2[%d]:%d\n",i,array2[i]) ;
i++;
}
i=0;
while(strarray[i].string) //在ASCII中转义字符'\0'对应时进制数是0,所以一个字符串为空""或是填0都可以作为数组遍历结束条件
{
printf("strarray[%d]:%s\n",i,strarray[i].string) ;
i++;
}
return0;
}
输出结果:
/*************知道数组大小来结束遍历数组****************/
array[0]:a=0,b=0
array[1]:a=1,b=2
array[2]:a=3,b=4
array[3]:a=0,b=0
array2[0]:1
array2[1]:2
array2[2]:3
array2[3]:0
/*************用数组最后一个元素来结束遍历数组****************/
array2[0]:1
array2[1]:2
array2[2]:3
strarray[0]:12345
strarray[1]:67890
11:结构体内数组成员如何初始化
typedef struct{
inttype;
unsigned scl;
unsigned sda;
void (*pinUnMapFunc)(void);
void (*pinMapFunc)(void);
}I2CHwDefTy;
typedef struct
{
I2CHwDefTy i2cs[SUPPORT_I2C_NUM];
}I2CConfigTy;
const I2CConfigTy i2c_conf ={
.i2cs = {
/*type SCL SDA unMapFunc MapFunc */
{0, GPIO_PA4, GPIO_PA3, i2c_ch0_unMap, i2c_ch0_map},
{0, GPIO_PB5, GPIO_PB4, i2c_ch1_unMap, i2c_ch1_map},
{0, GPIO_PD28, GPIO_PD27,i2c_ch2_unMap, i2c_ch2_map},
}
};
亦可写成
const I2CConfigTy i2c_conf ={
.i2cs = {
/*type SCL SDA unMapFunc MapFunc */
数组成员就是[0],而不是.[0]了!
[0]={0, GPIO_PA4, GPIO_PA3, i2c_ch0_unMap, i2c_ch0_map},
{0, GPIO_PB5, GPIO_PB4, i2c_ch1_unMap, i2c_ch1_map},
{0, GPIO_PD28, GPIO_PD27,i2c_ch2_unMap, i2c_ch2_map},
}
};
我的想法:[0]是划分了一块内存,即使你不填入数据这块内存也已经分配好了{0, GPIO_PA4, , }
. 符合代表初始化哪一个结构体成员变量
12:结构体数组的成员初始化
typedef struct{
unsignedint base;
unsignedint fclk;
unsignedint irq;
XDMA_Peripheral_TypeDeftx_dma_perip;
XDMA_Peripheral_TypeDefrx_dma_perip;
}UartDescTypedef;
static const UartDescTypedef uartDesc[UART_CH_MAX]={
{0x400E0800,100000000,7,XDMA_UART0_TX,XDMA_UART0_RX},
{0x400E0A00,100000000,8,XDMA_UART1_TX,XDMA_UART1_RX},
{0x400E1A00,100000000,44,XDMA_UART2_TX,XDMA_UART2_RX},
{0x400E1C00,100000000,45,XDMA_UART3_TX,XDMA_UART3_RX},
{0x400E1E00,100000000,46,XDMA_UART4_TX,XDMA_UART4_RX},
};
13:结构体内用define
typedef struct {
#define UART_WE 0
#define UART_RD 1
unsigned charflags; //
unsigned char* buf;
unsigned int len; //transfer length
void (*complete_handler)(constvoid*);
}UART_MsgTy;
14:异或
异或1:取反
异或0:不变
15:while(i--)
int main(void)
{
int i=10;
while(i--)
{
/*由此可知,while(i--)是先判断i条件,在i--,然后进入循环体*/
printf("i = %d\t", i);
}
return 0;
}
//运行结果i = 9 i = 8 i = 7 i = 6 i = 5 i = 4 i = 3 i = 2 i = 1 i = 0
15:字符串和数组
#include <stdio.h>
int main(void) {
char str1[]="1234567"; //存在栈里
char *str2="123456"; //str2存在栈里,"123456"存在常量区,不可以修改
char*str3="123456"; //str3存在栈里,str3指向的和str2是常量区里同一块内存 str1[0] = '0';
//str2[0] = '0';
printf("%s\n",str1);
printf("%s\n",str2);
return 0;
}