#include"stdlib.h"
#include<stdio.h>
#define min(A,B) ( (A) <= (B) ? (A):(B) )/*编译预处理替换-头文件,宏,条件编译。去注释,加行号*/
#define count(table) (sizeof(table)/sizeof(table[0]))/*数组长度除以数组元素长度*/
#define reg (*(volatile unsigned long *)0x48000004)/*后面reg = 0x12;直接解引用赋值*/
#define year (365*24*60*60) (UL) /*16位整型数溢出,用UL无符号长整型告诉编译器*/
int main(){
/*least = min(*p++,5); p会两次自增;*/
/*********************************************************************************************
宏不占运行,占编译,函调(分配单元,保留现场,值传递,返回);带参宏处理时不分配内存,函调
分配临时内存;宏不存在类型问题,宏名,参数无类型,函调实参形参皆定义类型,二者类型一致;使
用宏定义次数多,替换后源程序变长,函调不会使源程序变长。
内联函数->>优点:类宏,原地展开,省函调开销,可做类型检查;缺点:使程序代码量变大,耗内存。
适用于:函数体内无循环(执行时间短)且代码简短(占内存空间小)
关键字volatile->>作用:让编译器不优化(假设)变量值,因为它可能会被意外改变。即优化器在使用
变量时必须小心重新读取,而非使用保留于寄存器中的备份。例子:1、并行设备硬件寄存器(状态)。
2、一个中断服务子程序中会被访问到的非自动变量。3、多线程应用被几个线程共享变量(防死锁)。
关键字static->>修饰局部变量:1、改变存储位置,存储于静态区;2、改变其生命周期为整个源程序,
因此它只被初始化一次,若无显示初始化自动初始化为0;修饰全局变量:改变作用域,只能被文件内所
用函数访问;修饰函数时:改变作用域,只能被文件内的其他函数调用。
关键字extern->>跨文件引用全局变量,注:1、引用不能初始化;2、函数默认extern类型的,表面整个
程序可见,加不加都一样。extern”C”的作用: 在C++代码中调用C函数,用法:extern "C" {C函数库
头文件/函数声明}。注意:extern"C"只能用于C++文件中。
关键字auto->>自动局部变量在进入声明该变量的语句块时被建立,退出语句块时被注销,仅在语句块内
部使用。解读:其实普通局部变量就是自动局部变量,只是省略了auto这一关键字。
关键字register->>编译器将其修饰的变量尽量放CPU寄存器中, 加快存取速度, 用于频繁使用的变量;
注意:register变量可能不放在内存中,故不能用&来获取该变量的地址;只有局部变量和形参可以作为
register变量;寄存器数量有限,不能定义过多register变量。
volatile在编译阶段,extern在链接阶段。解读:C语言编译过程分为预处理、编译、汇编、链接。
const与#define->>异同:const有数据类型可以被静态类型检查,宏无;两者都可用来定义常数。
***********************************************************************************************/
#ifdef XXX /*遇到 #error 就会跳出一个编译错误。外部或者头文件指定宏(makefile),预处理检测*/
#error "XXX has been defined"
#else
#endif
auto char c = '0', count = 0, *s = "AAA";
int table[] = {1,2,3, 9,5},b = 29;
/*const放在*前是修饰指向的对象,放在*后则是修饰指针本身。*/
const int a1 = 9;/*等价于int const a; ->a为一个整形常量*/
const int *a2 = &b;/*->a是一个指向整型常量的指针变量,a2和*a2都要赋值*/
int *const a3 = &b;/*->a是一个指向整型变量的常指针*/
int const * const a4 = &b;/*->a是一个指向整型常量的常指针*/
// char *strcpy(char *strdest,const char *strsrc);/*参数在函数内部不会被修改*/
// const int strcmp(char *source,char *dest); /*函数返回值不可被修改/
int *a5[10]; /*一个指向10个指针的数组,指针数组*/
int (*a6)[10];/*一个指向10个整型数数组的指针,数组指针*/
// int (*a7)(int)/*一个指向函数的指针,有一个整型参数且返回一个整型数,函数指针*/
// int (*a8[10])(int)/*一个有10个指针的数组,10指针均指向函数,函数整型参数并返回一个整型数,函数指针数组*/
int *a = (int *)2;
printf("The value is %s %d", s,a+3); /*强制类型转换,int指针加3等于指向第三个int类型首地址,2+3*4字节*/
return 0;
}
/*一个参数既可以是const还可以是volatile吗?一个指针可以是volatile吗?下面的函数有什么问题?
一个例子是只读的状态寄存器,它可能被意想不到地改变,程序不应该试图去修改它。
一个例子是当一个中服务子程序修改一个指向一个缓冲区的指针时。
int square(volatile int *ptr) { return *ptr * *ptr; } 可能为:
int square(volatile int *ptr)
{
int a, b;
a = *ptr;
b = *ptr;
return a * b;
} 修改为:
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
#define dPS struct s * //(#号) dPS p1, p2;
typedef struct s * tPS; //(顺序、分号) tPS p3, p4;
-> struct s * p1, p2; //p2为一个实际的结构体,这也许不是想要的,typedef更好
strlen(字符数组名)得到字符串所占字节数,strlen(字符串指针名)得到字符串所占字节数。sizeof关键字用
来计算变量、数据类型所占内存字节数。
表达式中存在有符号数和无符号数时,有符号数隐式转换成了无符号数,-20补码为反码加一,为大整数。
写出float x与“零值”比较的if语句: if(x > -0.000001 && x < 0.000001);处理浮点有误差,不能“==,!=”
char *s = "AAA"; s[0] = 'B'; printf("%s", s); C语言没有整体处理一个字符串的机制,"AAA"是字符串
常量,s是指针,s指向这个字符串常量,声明s就有问题,应该是cosnt char* s="AAA"。s[0]的赋值操作不合法。
*/