c/c++小知识

一,C语言中预处理宏定义#defiine,文件包含 #include,条件编译#ifdef
不带参数的宏定义:#define 宏名 (字符串)
1.用宏名简单的置换字符串,不作正确性检查。2.宏定义不是C语句,不必要行末加分号,如果加了分号也可连分号一起进行置换。因此字符串最好用括号括起来。
3.习惯用大写字母表示,以便与变量名相区别,但这并非规定,也可以用小写。
4,#define 命令出现在程序中函数的外面,宏名的有效范围为定义命令之后到本源文件结束,通常 #define 命令写在文件开头,函数之前,作为文件一部分,在此文件范围内有效。
5,以用 #undef 命令终止宏定义的作用域。
如:

#define G 9.8
  void main()
  {
    ......
  }
  #undef G
  f()
  {
    .....
  }

由于#undef 的作用,使G的作用范围在 #undef 行处终止,因些在f函数中,G不再表9.8。
带参数的宏定义:#define 宏名(参数表) (字符串)
1,不是进行简单的字符串替换,还要进行参数替换。
#define S(a, b) a * b
  area = S(3, 2);
  因此展开得到
  area = 3 * 2;

宏如 S(3, 2) ,3置换a,2置换b,字符串中的字符不是参数的字符 如 (a * b 中的 * 号)则保留,这样就形成了置换字符串(3 * 2)。
2,形式参数最好用括号括起来:
如:#define S® PI * r * r
有:area = S(a + b);
  这时把实参 a + b 代替 PI * r * r 中的形参 r 成为
  area = PI * a + b * a + b;
  请注意在 a + b 外面没有括弧,显然这与程序设计都的愿意不符,愿意希望得到
  area = PI * (a + b) * (a + b);
  为了得到这个结果,应当在定义时,在字符串中的形式参数外面加一个括号即:
  #define S® PI * ® * ®
3,带参数宏与函数区别
a.函数调用时先求出实参表达式的值,然后代入形参,面使用带参数的宏只是进行简单的字符替换。
b.函数调用是在程序运行时处理的,分配临时的内存单元,而宏展开是在编译时进行的,在展开时并不分配内存单元,不进行值的传递处理,也没有返回值的概念。
c.对函数中的实参和形参都要定义类型,二者的类型要求一致,如果不一致应进行类型转换,而宏不存在类型问题,宏名无类型,它的参数也无类型,只是一个符号代表展开时代入指定的字符即可。宏定义时字符串可以是任何类型的数据。

**二,**文件包含#include “文件名” 或 #include <文件名>
所谓文件包含处理是指一个源中以将另外一个源文件的全部内容包含进来,即将另外的文件包含到本文件之中。
(1)一个include 命令只能指定一个被包含的文件,如果要包含n个文件,要用n个include 命令。
(2)如果文件1包含文件2而文件2中要用到文件3的内容,则可以在文件1中用两个include 命令分别包含文件2和文件3,而且文件3应出现在文件2前即:在file1.c中定义:
#include “file3.h”
  #include “file2.h”
这样file1 file2都可以用file3的内容,在file2中不必再用 #include <file3.h>
(3)在一个被包含文件中又可以包含另一个被包含文件,即文件包含是可以嵌套的。
(4)在 #include 命令中,文件名可以用双引号或尖括号。

如:#include <file2.h> 或 #include “file2”

二者的区别与使用:
用尖括弧时,称为标准方式,系统到存放C库函数头文件所在目录寻找要包含的文件。要包含是C库函数用尖括号。
用双引号时,先在用户当前目录中寻找要包含的文件,若找不到,再按标准方式查找。要包含是用户自己编写的文件,用双引号。
5)被包含文件(file2.h)与其所在的文件(即用 #include 命令的源文件file.c)在预编译后已成为同一个文件,(而不是两个文件)因此如果file2.h中有全局静态变量它也在file1.c文件中有效,不必用extern声明。当一个全局变量需要多文件中使用的时候,应当把这个变量的定义放在.cpp文件,把extern 变量名 放在.h文件。

三,C语言中#和##操作符分析#和##操作符
#运算符用于在预处理期将宏参数转换为字符串
##运算符用于在预处理期粘连两个标识符
**3)**C语言中的__FILE__、__LINE__和__func__等预定义跟踪调试FILELINE__和__func
LINE :当前程序行的行号,表示为十进制整型常量
FILE :当前源文件名,表示字符串型常量
DATE :转换的日历日期,表示为Mmm dd yyyy 形式的字符串常量,Mmm是由asctime产生的。
TIME :转换的时间,表示"hh:mm:ss"形式的字符串型常量,是有asctime产生的。(asctime貌似是指的一个函数)
四,C语言中空(null)指针和NULL的区别详解空(null)指针和NULL指针

对于空(null)指针的概念,在 C 标准中明确地定义:值为 0 的整型常量表达式,或强制(转换)为“void*”类型的此类表达式,称为空指针常量。当将一个空指针常量赋予一个指针或与指针作比较时,将把该常量转换为指向该类型的指针,这样的指针称为空指针。
0、0L、’\0’、3-3、017以及(void)0等都是空指针常量

int *p;
p=0;
/*或者*/
p=0l;
/*或者*/
p='\0';
/*或者*/
p=3-3;
/*或者*/
p=0*17;
/*或者*/
p=(void*)0;

指针变量 p 经过上面任何一种赋值操作之后都将成为一个空指针
在这里插入图片描述
标准 C 专门定义了一个标准预处理宏 NULL,其值为“空指针常量”,通常是 0 或者“((void*)0)”,即在指针上下文中的 NULL 与 0 是等价的,而未加修饰的 0 也是完全可以接受的

常数 0 是一个空指针常量,而 NULL 仅仅是它的一个别名。NULL 可以确保是 0,但空(null)指针却不一定,用空指针常量初始化该类型的指针,该指针就变成空指针
空指针做如下几点剖析:
1) 每一种指针类型都有一个空指针,它与同类型的其他所有指针值都不相同。
2) 由系统保证空指针不指向任何实际的对象或函数,也就是说,任何对象或者函数的地址都不可能是空指针,空指针与任何对象或函数的指针值都不相等。因此,取地址操作符 & 永远也不能得到空指针,同样对 malloc() 函数的成功调用也不会返回空指针,但如果调用失败,则 malloc() 函数返回空指针。
3) 空指针表示“未分配”或者“尚未指向任何地方”。它与未初始化的指针有所不同,空指针可以确保不指向任何对象或函数,而未初始化指针可能指向任何地方。

头文件:#include <string.h>
memcpy() 用来复制内存,其原型为:
void * memcpy ( void * dest, const void * src, size_t num );
memcpy() 会复制 src 所指的内存内容的前 num 个字节到 dest 所指的内存地址上。

memcpy() 并不关心被复制的数据类型,只是逐字节地进行复制,这给函数的使用带来了很大的灵活性,可以面向任何数据类型进行复制。

需要注意的是:
dest 指针要分配足够的空间,也即大于等于 num 字节的空间。如果没有分配空间,会出现断错误。
dest 和 src 所指的内存空间不能重叠(如果发生了重叠,使用 memmove() 会更加安全)。

与 strcpy() 不同的是,memcpy() 会完整的复制 num 个字节,不会因为遇到“\0”而结束。

【返回值】返回指向 dest 的指针。注意返回的指针类型是 void,使用时一般要进行强制类型转换。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值