2017-12-27 15:19:58 qq_28349403 阅读数 1817
  • 172集通俗易懂的C语言从入门到项目实战教程

    1) 本套课程针对高校大学生系统学习C语言而录制,从0基础入门讲起,循序渐进,通俗易懂,同时适用于计算机系及非计算机系的同学。通过学习可以帮助大家掌握C语言本质,轻松面对C语言全国二级考试,并达到能独立完成中型C项目、C游戏的水平; 2) 多数高校都开设了C语言课程,网上C语言课程也很多,但普遍存在两个问题: (1) 授课方式单一,大多是照着代码念一遍, 对刚刚接触编程的同学来说,感觉晦涩难懂 (2) 授课内容过度注重语法,没有项目实战支撑,造成课程枯燥无趣。本课程针对上述问题进行了改进 (1) 授课方式采用语法讲解+内存布局示意图+项目的方式,让课程生动有趣好理解 (2) 系统全面的讲解了C语言的核心技术点,还配套录制了《全国计算机二级C语言真题精讲》,让学员在掌握C语言编程的同时,还能轻松面对二级考试;3) 课程详细内容: 常量-变量、分支语句、循环语句、操作符和表达式、函数(库函数、自定义函数、递归调用 )、数组(一维数 组、二维数组、数组作为函数参数、指针数组)、指针(指针和指针类型、二级指针和多级指针、指针表达式解析、指针运算、数 组指针、函数指针、回调函数)、调试技巧、程序环境和预处理(翻译环境、运行环境、预定义符号、#define和#undef、宏和函 数、条件编译、文件包含)、 数据在内存中的存储、内存块分配、static、字符函数和字符串函数、自定义类型(结构体、枚举 、联合)、动态内存管理、文件操作(i/o常量、i/o函数、流)。

    45 人正在学习 去看看 张长志

用法:#undef 标识符

其中,标识符是一个宏名称。如果标识符当前没有被定义成一个宏名称,则忽略该指令。

如果定义预处理器标识符,那么它将保持已定义状态且在作用域内,直到程序结束或者使用#undef指令取消定义。例如:起初定义了一个标识符,之后#undef 标识符,在该行之后,又调用该标识符,则程序会编译出错。

列举一个实例:从网上看到的

#include <iostream> 
  #include<string>
  #define MAX 5 
  #undef MAX 
  void main() 
  { 
  char name[MAX]="abcde"; //只能用abcd,否则会提示说超出长度,原因大概是"/0"字符
  cout<<"MAX = "<<MAX<<endl; 
  for(int i=0;i<MAX;i++) 
  cout<<name<<" "<<endl;
  } 

其中的MAX,就是上面所说的情况。

2010-05-31 13:28:00 ralphsage 阅读数 1208
  • 172集通俗易懂的C语言从入门到项目实战教程

    1) 本套课程针对高校大学生系统学习C语言而录制,从0基础入门讲起,循序渐进,通俗易懂,同时适用于计算机系及非计算机系的同学。通过学习可以帮助大家掌握C语言本质,轻松面对C语言全国二级考试,并达到能独立完成中型C项目、C游戏的水平; 2) 多数高校都开设了C语言课程,网上C语言课程也很多,但普遍存在两个问题: (1) 授课方式单一,大多是照着代码念一遍, 对刚刚接触编程的同学来说,感觉晦涩难懂 (2) 授课内容过度注重语法,没有项目实战支撑,造成课程枯燥无趣。本课程针对上述问题进行了改进 (1) 授课方式采用语法讲解+内存布局示意图+项目的方式,让课程生动有趣好理解 (2) 系统全面的讲解了C语言的核心技术点,还配套录制了《全国计算机二级C语言真题精讲》,让学员在掌握C语言编程的同时,还能轻松面对二级考试;3) 课程详细内容: 常量-变量、分支语句、循环语句、操作符和表达式、函数(库函数、自定义函数、递归调用 )、数组(一维数 组、二维数组、数组作为函数参数、指针数组)、指针(指针和指针类型、二级指针和多级指针、指针表达式解析、指针运算、数 组指针、函数指针、回调函数)、调试技巧、程序环境和预处理(翻译环境、运行环境、预定义符号、#define和#undef、宏和函 数、条件编译、文件包含)、 数据在内存中的存储、内存块分配、static、字符函数和字符串函数、自定义类型(结构体、枚举 、联合)、动态内存管理、文件操作(i/o常量、i/o函数、流)。

    45 人正在学习 去看看 张长志

涉及源码文件:drivers/mtd/maps/alchemy-flash.c

 

10:   #include <linux/config.h>

注解: 在 include/linux/config.h中,只有一句 #include <linux/autoconf.h>, 而在 include/linux/autoconf.h 中则有如下

59:  #undef CONFIG_MIPS_PB1000
60:  #undef CONFIG_MIPS_PB1100
61:  #undef CONFIG_MIPS_PB1500
62:  #undef CONFIG_MIPS_PB1550
63:  #undef CONFIG_MIPS_PB1200
64:  #undef CONFIG_MIPS_DB1000
65:  #undef CONFIG_MIPS_DB1100
66:  #undef CONFIG_MIPS_DB1500
67:  #undef CONFIG_MIPS_DB1550
68: 
#define CONFIG_MIPS_DB1200 1

 

因此对应于alchemy-flash.c 的82行定义成立

#ifdef CONFIG_MIPS_DB1200
#define BOARD_MAP_NAME "Db1200 Flash"
#define BOARD_FLASH_SIZE 0x00800000 /* 8MB */
#define BOARD_FLASH_WIDTH 2 /* 16-bits */
#endif

 

其中 BOARD_FLASH_SIZE 表示嵌入式系统中使用的NorFlash的容量大小, BOARD_FLASH_WIDTH 表示NorFlash数据总线宽度(以byte为单位)。

 

 

在 include/linux/mtd/partitions.h中定义结构体

struct mtd_partition {
    char *name;            /* identifier string */
    u_int32_t size;            /* partition size */
    u_int32_t offset;        /* offset within the master MTD space */
    u_int32_t mask_flags;        /* master MTD flags to mask out for this partition */
    struct nand_oobinfo *oobsel;    /* out of band layout for this partition (NAND only)*/
    struct mtd_info **mtdp;        /* pointer to store the MTD object */
};

 

 

alchemy-flash.c 的 113行开始的定义则对应于NorFlash中的分区方案:

 

static struct mtd_partition alchemy_partitions[] = {
        {
                .name = "User FS",
                .size = BOARD_FLASH_SIZE - 0x00400000,  ——此处即使用宏
BOARD_FLASH_SIZE
                .offset = 0x0000000
        },

        {
                .name = "YAMON",
                .size = 0x0100000,
                .offset = MTDPART_OFS_APPEND,
            //    .mask_flags = MTD_WRITEABLE

                ——此处使用的宏 MTD_WRITEABLE 表示 本mtd分区起始偏移量紧跟上一分区结束位置
        },
        {
                .name = "raw kernel",
                .size = (0x300000 - 0x40000), /* last 256KB is yamon env */
                .offset = MTDPART_OFS_APPEND,
        }
};


在这个NorFlash分区的方案中,YAMON 开始于 NorFlash的最后 4MB 起始处,整个kernel 和 Yamon占据 NorFlash最后 4MB 空间,这可从"User FS" .size= BOARD_FLASH_SIZE - 0x00400000 看出


因此,当NorFlash类型更换之后,需要根据新NorFlash的容量、数据宽度相应的修改 alchemy-flash.c  82行开始的宏定义 BOARD_FLASH_SIZE   和 BOARD_FLASH_WIDTH

2017-07-06 15:53:21 zhanghao864442969 阅读数 1595
  • 172集通俗易懂的C语言从入门到项目实战教程

    1) 本套课程针对高校大学生系统学习C语言而录制,从0基础入门讲起,循序渐进,通俗易懂,同时适用于计算机系及非计算机系的同学。通过学习可以帮助大家掌握C语言本质,轻松面对C语言全国二级考试,并达到能独立完成中型C项目、C游戏的水平; 2) 多数高校都开设了C语言课程,网上C语言课程也很多,但普遍存在两个问题: (1) 授课方式单一,大多是照着代码念一遍, 对刚刚接触编程的同学来说,感觉晦涩难懂 (2) 授课内容过度注重语法,没有项目实战支撑,造成课程枯燥无趣。本课程针对上述问题进行了改进 (1) 授课方式采用语法讲解+内存布局示意图+项目的方式,让课程生动有趣好理解 (2) 系统全面的讲解了C语言的核心技术点,还配套录制了《全国计算机二级C语言真题精讲》,让学员在掌握C语言编程的同时,还能轻松面对二级考试;3) 课程详细内容: 常量-变量、分支语句、循环语句、操作符和表达式、函数(库函数、自定义函数、递归调用 )、数组(一维数 组、二维数组、数组作为函数参数、指针数组)、指针(指针和指针类型、二级指针和多级指针、指针表达式解析、指针运算、数 组指针、函数指针、回调函数)、调试技巧、程序环境和预处理(翻译环境、运行环境、预定义符号、#define和#undef、宏和函 数、条件编译、文件包含)、 数据在内存中的存储、内存块分配、static、字符函数和字符串函数、自定义类型(结构体、枚举 、联合)、动态内存管理、文件操作(i/o常量、i/o函数、流)。

    45 人正在学习 去看看 张长志

Linux 2.6.22的u盘代码实现中有如下代码

第一种宏定义

#ifndef CONFIG_USB_LIBUSUAL

#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
		    vendorName, productName,useProtocol, useTransport, \
		    initFunction, flags) \
{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }

#define USUAL_DEV(useProto, useTrans, useType) \
{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
  .driver_info = (USB_US_TYPE_STOR<<24) }

static struct usb_device_id storage_usb_ids [] = {

#	include "unusual_devs.h"
#undef UNUSUAL_DEV
#undef USUAL_DEV
	/* Terminating entry */
	{ }
};

MODULE_DEVICE_TABLE (usb, storage_usb_ids);
#endif /* CONFIG_USB_LIBUSUAL */

第二种宏定义

#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
		    vendor_name, product_name, use_protocol, use_transport, \
		    init_function, Flags) \
{ \
	.vendorName = vendor_name,	\
	.productName = product_name,	\
	.useProtocol = use_protocol,	\
	.useTransport = use_transport,	\
	.initFunction = init_function,	\
}

#define USUAL_DEV(use_protocol, use_transport, use_type) \
{ \
	.useProtocol = use_protocol,	\
	.useTransport = use_transport,	\
}

static struct us_unusual_dev us_unusual_dev_list[] = {
#	include "unusual_devs.h" 
#	undef UNUSUAL_DEV
#	undef USUAL_DEV

	/* Terminating entry */
	{ NULL }
};

unusual_devs.h中内容大致如下

UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999,
		"Casio",
		"QV DigitalCamera",
		US_SC_8070, US_PR_CB, NULL,
		US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ),

/* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/
UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
		"Samsung",
		"Digimax 410",
		US_SC_DEVICE, US_PR_DEVICE, NULL,
		US_FL_FIX_INQUIRY),

UNUSUAL_DEV(  0x084d, 0x0011, 0x0110, 0x0110,
		"Grandtech",
		"DC2MEGA",
		US_SC_DEVICE, US_PR_DEVICE, NULL,
		US_FL_BULK32),

/* Submitted by Jan De Luyck <lkml@kcore.org> */
UNUSUAL_DEV(  0x08bd, 0x1100, 0x0000, 0x0000,
		"CITIZEN",
		"X1DE-USB",
		US_SC_DEVICE, US_PR_DEVICE, NULL,
		US_FL_SINGLE_LUN),
/* Control/Bulk transport for all SubClass values */
USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_QIC, US_PR_CB, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_UFI, US_PR_CB, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_8070, US_PR_CB, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_SCSI, US_PR_CB, USB_US_TYPE_STOR),

/* Control/Bulk/Interrupt transport for all SubClass values */
USUAL_DEV(US_SC_RBC, US_PR_CBI, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_8020, US_PR_CBI, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_QIC, US_PR_CBI, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_UFI, US_PR_CBI, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_8070, US_PR_CBI, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_SCSI, US_PR_CBI, USB_US_TYPE_STOR),

/* Bulk-only transport for all SubClass values */
USUAL_DEV(US_SC_RBC, US_PR_BULK, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_8020, US_PR_BULK, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_QIC, US_PR_BULK, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_UFI, US_PR_BULK, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_8070, US_PR_BULK, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_SCSI, US_PR_BULK, 0),

如上就实现了用同一个文件实现了us_unusual_dev_list和storage_usb_ids不同结构体类型数组的初始化

使用方法

#define  AAA2


int a1 = AAA;

#undef  AAA


#define  AAA'2'

char a2= AAA;

这样a1和a2的不同类型,却都可以使用AAA来初始化

2011-03-09 16:34:00 satanwxd 阅读数 6761
  • 172集通俗易懂的C语言从入门到项目实战教程

    1) 本套课程针对高校大学生系统学习C语言而录制,从0基础入门讲起,循序渐进,通俗易懂,同时适用于计算机系及非计算机系的同学。通过学习可以帮助大家掌握C语言本质,轻松面对C语言全国二级考试,并达到能独立完成中型C项目、C游戏的水平; 2) 多数高校都开设了C语言课程,网上C语言课程也很多,但普遍存在两个问题: (1) 授课方式单一,大多是照着代码念一遍, 对刚刚接触编程的同学来说,感觉晦涩难懂 (2) 授课内容过度注重语法,没有项目实战支撑,造成课程枯燥无趣。本课程针对上述问题进行了改进 (1) 授课方式采用语法讲解+内存布局示意图+项目的方式,让课程生动有趣好理解 (2) 系统全面的讲解了C语言的核心技术点,还配套录制了《全国计算机二级C语言真题精讲》,让学员在掌握C语言编程的同时,还能轻松面对二级考试;3) 课程详细内容: 常量-变量、分支语句、循环语句、操作符和表达式、函数(库函数、自定义函数、递归调用 )、数组(一维数 组、二维数组、数组作为函数参数、指针数组)、指针(指针和指针类型、二级指针和多级指针、指针表达式解析、指针运算、数 组指针、函数指针、回调函数)、调试技巧、程序环境和预处理(翻译环境、运行环境、预定义符号、#define和#undef、宏和函 数、条件编译、文件包含)、 数据在内存中的存储、内存块分配、static、字符函数和字符串函数、自定义类型(结构体、枚举 、联合)、动态内存管理、文件操作(i/o常量、i/o函数、流)。

    45 人正在学习 去看看 张长志

在编写网络程序时,会涉及到一些关于BSD系统保留下的结构体和宏定义,关于一切配置在linux系统的/usr/include/features.h文件中,开启项如下:

#ifdef _GNU_SOURCE
# undef  _ISOC99_SOURCE
# define _ISOC99_SOURCE 1
# undef  _POSIX_SOURCE
# define _POSIX_SOURCE  1
# undef  _POSIX_C_SOURCE
# define _POSIX_C_SOURCE        199506L
# undef  _XOPEN_SOURCE
# define _XOPEN_SOURCE  600
# undef  _XOPEN_SOURCE_EXTENDED
# define _XOPEN_SOURCE_EXTENDED 1
# undef  _LARGEFILE64_SOURCE
# define _LARGEFILE64_SOURCE    1
# undef  _BSD_SOURCE
# define _BSD_SOURCE    1
# undef  _SVID_SOURCE
# define _SVID_SOURCE   1
#endif
可以看出只要开启了_GNU_SOURCE的花,大部分的BSD功能可以打开,看看_GNU_SOURCE是否开启有一个测试程序:

#include <iostream>

int main()
{
#ifdef _GNU_SOURCE
  std::cout << "gnu/n";
#else
  std::cout << "non-gnu/n";
#endif
}
只要gcc -D _GNU_SOURCE test.c -o test.o编译生成的text.o文件,运行一下就知道是否开启了

2015-12-23 13:07:08 zqixiao_09 阅读数 2277
  • 172集通俗易懂的C语言从入门到项目实战教程

    1) 本套课程针对高校大学生系统学习C语言而录制,从0基础入门讲起,循序渐进,通俗易懂,同时适用于计算机系及非计算机系的同学。通过学习可以帮助大家掌握C语言本质,轻松面对C语言全国二级考试,并达到能独立完成中型C项目、C游戏的水平; 2) 多数高校都开设了C语言课程,网上C语言课程也很多,但普遍存在两个问题: (1) 授课方式单一,大多是照着代码念一遍, 对刚刚接触编程的同学来说,感觉晦涩难懂 (2) 授课内容过度注重语法,没有项目实战支撑,造成课程枯燥无趣。本课程针对上述问题进行了改进 (1) 授课方式采用语法讲解+内存布局示意图+项目的方式,让课程生动有趣好理解 (2) 系统全面的讲解了C语言的核心技术点,还配套录制了《全国计算机二级C语言真题精讲》,让学员在掌握C语言编程的同时,还能轻松面对二级考试;3) 课程详细内容: 常量-变量、分支语句、循环语句、操作符和表达式、函数(库函数、自定义函数、递归调用 )、数组(一维数 组、二维数组、数组作为函数参数、指针数组)、指针(指针和指针类型、二级指针和多级指针、指针表达式解析、指针运算、数 组指针、函数指针、回调函数)、调试技巧、程序环境和预处理(翻译环境、运行环境、预定义符号、#define和#undef、宏和函 数、条件编译、文件包含)、 数据在内存中的存储、内存块分配、static、字符函数和字符串函数、自定义类型(结构体、枚举 、联合)、动态内存管理、文件操作(i/o常量、i/o函数、流)。

    45 人正在学习 去看看 张长志
1.预处理程序
按照ANSI标准的定义,预处理程序应该处理以下指令:
#if #ifdef #ifndef #else #elif
#endif
#define
#undef
#line
#error
#pragma
#include
显然,上述所有的12个预处理指令都以符号#开始,每条预处理指令必须独占一行。

2.#define
#define指令定义一个标识符和一个串(也就是字符集),在源程序中发现该标识符时,都用该串替换之。这种标识符称为宏名字,相应的替换称为宏代换。一般形式如下:
#define macro-name char-sequence
这种语句不用分号结尾。宏名字和串之间可以有多个空白符,但串开始后只能以新行终止。
例如:我们使用LEFT代表1,用RIGHT代表0,我们使用两个#define指令:
#define LEFT 1
#define RIGHT 0
每当在源程序中遇到LEFT或RIGHT时,编译程序都用1或0替换。
定义一个宏名字之后,可以在其他宏定义中使用,例如:
#define ONE 1
#define TWO ONE+ONE
#define THREE ONE+TWO
宏代换就是用相关的串替代标识符。因此,如果希望定义一条标准错误信息时,可以如下定义:
#define ERROR_MS “Standard error on input \n”
如果一个串长于一行,可在行尾用反斜线”\”续行,如下:
#define LONG_STRING “This is a very very long \
String that is used as an example”
我们可以用宏写函数:
#define SWAP(a,b)    \
{                    \
int temp = a;        \
a = b;               \
b = temp;            \
}                    \ 
这里的"\"意为这是条整语句,编译完成后,函数如果调用了SWAP(a,b),就变成了{int temp = a; a = b;b = temp;};
宏定义函数与外部调用函数对比:
1)宏定义优点:效率高,因为函数调用涉及压栈,出栈,而宏定义函数不需要;
2)宏定义缺点:占空间,因为没有压栈和出栈,就会一直占着内存;
宏定义是空间换时间

3.#error
#error指令强制编译程序停止编译,它主要用于程序调试。#error指令的一般形式是:
#error error-message
注意,宏串error-message不用双引号包围。遇到#error指令时,错误信息被显示,可能同时还显示编译程序作者预先定义的其他内容。

4.#include
  文件包含
程序中的#include指令要求编译程序读入另一个源文件。被读入文件的名字必须用双引号(“”)或一对尖括号(<>)包围。
例如:
#include “stdio.h”
#include  <stdio.h>
都使C编译程序读入并编译头文件以用于I/O系统库函数。
包含文件中可以包含其他#include指令,称为嵌套包含。允许的最大嵌套深度随编译器而变。
文件名被双括号或尖括号包围决定了对指定文件的搜索方式:
1)文件名被尖括号包围时,搜索按编译程序作者的定义进行,一般用于搜索某些专门放置包含文件的特殊目录。
2)当文件名被双括号包围时,搜索按编译程序实时的规定进行,一般搜索当前目录。如未发现,再按尖括号包围时的办法重新搜索一次。
 我们编译时也可以加入 gcc -I /home/fs/include  如果我们在当前目录里找不到"stdio.h",就会到/home/fs/include(这是我们自己存放头文件的位置)里去搜索,如果还是搜索不到,便会到系统头文件里去查找;
通常,绝大多数程序员使用尖括号包围标准的头文件,双引号用于包围与当前程序相关的文件名。
 
5. 条件编译指令
若干编译指令允许程序员有选择的编译程序源代码的不同部分,这种过程称为条件编译。
5.1#if、#else、#elif #endif
条件编译指令中最常用的或许是#if,#else,#elif和#endif。这些指令允许程序员根据常数表达式的结果有条件的包围部分代码。
#if的一般形式是:
#if constant-expression
 Statement sequence
#endif
如#if后的常数表达式为真,则#if和#endif中间的代码被编译,否则忽略该代码段。#endif标记#if块的结束。
 
#else指令的作用与C语言的else相似,#if指令失败时它可以作为备选指令。例如:
#include <stdio.h> 
#define MAX 100
 
Int main(void)
{
 #if MAX > 99
 	printf(“Compiled for array greater than 99.\n”);
 #else
 	printf(“Complied for small array.\n”);
 #endif
 return 0;
}

注意,#else既是标记#if块的结束,也标记#else块的开始。因为每个#if只能写一个#endif匹配。
 
#elif指令的意思是“否则,如果”,为多重编译选择建立一条if-else-if(如果-否则-如果链)。如果#if表达式为真,该代码块被编译,不测试其他#elif表达式。否则,序列中的下一块被测试,如果成功则编译之。一般形式如下:
#if expression
 Statement sequence
#elif expression1
 Statement sequence
#elif expression2
 Statement sequence
.
.
.
#elif expression
 Statement sequence
#endif

5.2#ifdef和#ifndef
条件编译的另一个方法是使用编译指令#ifdef和#ifndef,分别表示“如果已定义”和“如果未定义”。#ifdef的一般形式如下:

#ifdef 标识符 

Statement sequence

#endif

如果macro-name原先已经被一个#define语句定义,则编译其中的代码块。

#ifndef的一般形式是:

#ifndef 标识符

 Statement sequence

#endif

如果macro-name当前未被#define语句定义,则编译其中的代码块。
#ifdef和#ifndef都可以使用#else或#elif语句。

#inlucde <stdio.h> 
#define T 10
 
Int main(void)
{
 #ifdef t
 	printf(“Hi T\n”);
 #else
 	printf(“Hi anyone\n”);
 #endif
 #ifndef M
 	printf(“M Not Defined\n”);
 #endif
 
 Return 0;
}

6.#undef
#undef指令删除前面定义的宏名字。也就是说,它“不定义”宏。一般形式为:
#undef macro-name


7. #defined
除#ifdef之外,还有另外一种确定是否定义宏名字的方法,即可以将#if指令与defined编译时操作符一起使用。defined操作符的一般形式如下:
defined macro-name
如果macro-name是当前定义的,则表达式为真,否则为假。
例如,确定宏MY是否定义,可以使用下列两种预处理命令之一:
#if defined MY

#ifdef MY
也可以在defined之前加上感叹号”!”来反转相应的条件。例如,只有在DEBUG未定义的情况下才编译。
#if !defined DEBUG
 Printf(“Final Version!\n”);
#endif
使用defined的一个原因是,它允许由#elif语句确定的宏名字存在。


8.#line
#line指令改变__LINE__和__FILE__的内容。__LINE__和__FILE__都是编译程序中预定义的标识符。标识符__LINE__的内容是当前被编译代码行的行号,__FILE__的内容是当前被编译源文件的文件名。#line的一般形式是:
#line number “filename”
其中,number是正整数并变成__LINE__的新值;可选的“filename”是合法文件标识符并变成__FILE__的新值。#line主要用于调试和特殊应用。

9.#pragma
#pragma是编译程序实现时定义的指令,它允许由此向编译程序传入各种指令。例如,一个编译程序可能具有支持跟踪程序执行的选项,此时可以用#pragma语句选择该功能。编译程序忽略其不支持的#pragma选项。#pragma提高C源程序对编译程序的可移植性。


10. 预处理操作符#和##
有两个预处理操作符:#和##,它们可以在#define中使用。
操作符#通常称为字符串化的操作符,它把其后的串变成用双引号包围的串。例如:

#include <stdio.h> 
#define mkstr(s) #s
int main(void)
{
 	p(mkstr(I like C));
 
 	Return 0;
}

预处理程序把以下的语句:
Printf(mkstr(I like C));
变成
Printf(“I like C”);
操作符##把两个标记拼在一起,形成一个新标记。例如:

#include <stdio.h> 
#define concat(a,a) a##b
 
int main(void)
{
 Int xy = 10;
 Printf(“%d”,concat(x,y));
 Return 0;
}

预处理程序把以下语句:
Printf(“%d”,concat(x,y));
变成
Printf(“%d”,xy);
操作符#和##主要作用是允许预处理程序对付某些特殊情况,多数程序中并不需要。


11. 预定义宏
C规范了5个固有的预定义宏,它们是:
__LINE__
__FILE__
__DATE__
__TIME__
__STDC__
 
__LINE__和__FILE__包含正在编译的程序的行号和文件名。
__DATE__和内容形如month/day/year(月/日/年)的串,代表源文件翻译成目标码的日期。
__TIME__中的串代表源代码编译成目标码的时间,形如hour:minute:second(时:分:秒)
如果__STDC__的内容是十进制常数1,则表示编译程序的实现符合标准C。

 
附:
 在预处理中,我们经常用到define ,这里得提到 typedef ,二者用法很相似,大家还不要搞混;具体的区别是什么呢?
1、typedef 是C语言关键字
2、define 是预处理命令
这里介绍一下typedef的应用,typedef经常被用于为另一种数据类型定义一个新名字,在数据结构中更是频繁出现
typedef <已有数据类型> <新数据类型>
 
下面举个例子介绍:
typedef struct _node_
{
	int data;
	struct _node_ *next;
}listnode,*linklist;
这里定义了两个新的数据类型listnode和linklist。其中listnode等价于数据类型struct _node_ 而linklist等价于stuct _node_  *;
或者,我们这样理解,上面的定义就相当于:
struct _node_
{
	int data;
	struct _node_ *next;
};
typedef struct _node_ listnode;
typedef struct _node_ *linklist;


 

TCP/IP RAW ARP扫描

阅读数 1161

没有更多推荐了,返回首页