#define 除了定义常数之外,经常还用来定义字符串,尤其是路径。
用define来定义注释符号。
注释要先于预指令被处理,当这两行被展开成//...或/**/时,注释已处理完毕,此时再出现//...或/**/自然错误,因此试图用宏开始或结束一段注释是不行的。
#define与#的结合使用
#define与##的结合使用。
定义一个宏,实现一年有多少秒
//下面是网上推荐的,但是在VS中调试有错误。
#define SEC_PER_YEAR (60*60*24*365)UL
宏定义中的空格
定义宏的时候一定要注意什么时候该用空格,什么时候不该用空格。这个空格仅在定义的时候有效,在使用这个宏函数的时候,空格会被编译器忽略掉。
#undef撤销宏定义
#define X 3
#define Y X*2
#undef X
#define X 2
int z=Y;
z的值是多少呢?结果是4 Y字符替换之后一直是X*2,不会因为计算值而改变
#line 常量 “文件名”
#line 常量
使编译器认为(出于错误诊断目的):下一行源代码的行号是以十进制整型常量的形式给出的,并且,当前的输入文件是由该标识符命名的。如果缺少带双引号的文件名部分,则不改变当前编译的源文件的名字。命令#line主要用于调试和其他特殊作用。
#line 100 "123.txt"
printf("%s-----%d\n",__FILE__,__LINE__);
#error [error message]
当预处理器预处理到#error命令时将停止编译并输出用户自定义的错误消息。
#pragma Para
#pragma message("消息文本") 在编译窗口将消息文本打印出来
#pragma code_seg 它能够设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到它。
设定编译器或者指使编译器完成特定的动作
#pragma once 只要在头文件的最开始加入这条指令就能够保证头文件被编译一次,移植性较差,最好使用 #ifndef,#define,#endif对头文件进行控制
#pragma hdrstop 表示预编译头文件到此为止,后面的头文件不进行预编译。
#pragma startup指定编译优先级
#pragma package(smart_init) ,BCB就会根据优先级的大小先后编译。
#pragma resource "*.dfm"表示把*.dfm文件中的资源加入工程。*.dfm中包括窗体外观的定义。
#pragma warning( disable : 4507 34; once : 4385; error : 164 )
#pragma warning( push [ ,n ] )
#pragma warning( pop )
这里n代表一个警告等级(1---4)。
#pragma warning( push [ ,n ] )
#pragma warning( pop ) 这里n代表一个警告等级(1---4)。#pragma pack()规定的对齐长度,
为什么会有内存对齐?
牺牲一点空间为了提高程序的性能。为了访问未对齐的内存,处理器需要两次内存访问,对齐的内存访问需要一次访问就要以。
恩考如何来避免内存对齐?
注意:
每个成员按自己的方式对齐,并能最小化长度。
复杂类型(结构)的默认对齐方式是按它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度。
对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐。
查阅下面的例子:
/************************************************************************/
/*
** Filename:2013_0125.c
** Auth :hgj
** Description:内存对齐学习
** Note:
*/
/************************************************************************/
//#define FIRST_DEMO
#define SECOND_DEMO
#ifdef FIRST_DEMO
#include <stdio.h>
#include <conio.h>
int main(void)
{
typedef struct
{
char c1;
short s;
char c2;
int i;
}TestStruct;
TestStruct a;
printf("c1 %p,s %p,c2 %p,i %p\n",
(unsigned int )(void *)&a.c1 - (unsigned int)(void*)&a,
(unsigned int )(void *)&a.s - (unsigned int)(void*)&a,
(unsigned int )(void *)&a.c2 - (unsigned int)(void*)&a,
(unsigned int )(void *)&a.i - (unsigned int)(void*)&a);
printf("\nsizeof(long )=%d\n",sizeof(long));
printf("\nsizeof(long long)=%d\n",sizeof(long long));
getch();
return 0;
}
#elif defined SECOND_DEMO
#include <stdio.h>
#include <conio.h>
#pragma pack(8)
int main(void)
{
typedef struct
{
char a;
long b;
}TestStruct4;
typedef struct
{
char c;
TestStruct4 d;
long long e;
}TestStruct5;
TestStruct4 hgj;
printf("a %p,b %p\n",
(unsigned int )(void *)&hgj.a - (unsigned int)(void*)&hgj,
(unsigned int )(void *)&hgj.b - (unsigned int)(void*)&hgj);
printf("");
printf("\nsizeof(TestStruct4)=%d\n",sizeof(TestStruct4));
printf("\nsizeof(TestStruct5)=%d\n",sizeof(TestStruct5));
getch();
return 0;
}
#endif
#pragma comment(...) 该命令将一个注释记录放入一个对象文件或可执行文件中。
常用的lib关键字,可以帮助我们连入一个库文件,比如:
#pragma comment(lib,"user32.lib")
linker:将一个链接选项放入目标文件中,你可以使用这个指令来代替由命令行传入的或者在开发环境中设置的链接选项,你可以指定/include选项来强制包含某个对象,例如:
#pragma comment(linker,"/include:__mySymbol")
#
空指令,预处理器行不执行任何操作
下面这些标识符是预定义的,扩展后将生成特定的信息,它们同预处理器表达式运算符defined一样,不能取消预定义或重新进行定义。
__LINE__ 包含当前源文件行数的十进制常量
__FILE__ 包含正在被编译的源文件名字的字符串字面值
__DATE__ 包含编译日期的字符串字面值,其形式为:Mmm dd yyyy
__TIME__ 包含编译时间的字符串字面值,其形式为:hh:mm:ss
__STDC__ 整型常量1.只有在遵循标准的实现中该标识符才被定义为1.
__cplusplus