有书共读22《C primer Plus》16章

  1. 明示常量#define预处理字符:由3部分组成,第1部分是#define指令本身;第2部分是选定的缩写,也成为宏;第3部分(指令的其余部分)称为替换列表或替换体。
eg:#define PX printf(“*x is %d.\n”,x) 其中#define是指令本身;PX为宏;printf(“*x is %d.\n”,x)是替换体。

预处理器不做计算、不求值、只替换字符序列。

2、#define OW “consistency is the last refuge of the unimagina\

tive.-oscar while”我们在上一行的结尾加一个反斜杠字符使该行扩展至下一行,注意第2 行要与第一行左对齐。

3、重定义常量:只有新定义与旧定义完全相同才允许重定义。注:如果需要重定义宏,使用#undef指令。

4、预处理器粘合剂:##运算符。与#运算符类似,##运算符可用于类函数宏的替换部分,还可以用于对象宏的替换部分。eg: #define XNAME(n) x ## n

5、变参宏:…和_ _VA_ARGS_ _

  通过把宏参数列表中最后的参数写成省略号(即,3个点

  eg:#define PR(…) printf(__VA_ARGS__)

6、宏和函数的选择:

1)记住宏名中不允许有空格,但是在替换字符串中可以有空格。

2)用圆括号把宏的参数和整个替换体括起来,这样能确保被括起来的部分在表达式中正确。

3)用大写字母表示宏函数的名称

4)如果打算使用宏来加快程序的运行速度,那么首先要确定使用宏和使用函数是否会导致较大的差异。在程序中只使用一次的宏无法明显减少程序的运行时间。在嵌套循环中使用宏更有助于提高效率。

7、文件包含:#include

  eg:#include <stdio.h>和#include “mystuff.h”

  UNIX系统中,尖括号告诉预处理器在标准系统目录中查找该文件。双引号告诉预处理器首先在当前目录中(或该文件名中指定的其他目录)查找该文件。

 注:可执行代码通常在源代码文件中,而不是在头文件中。

8#undef指令:用于取消已定义的#define指令。

  eg:#define LIMIT 400
      #undef LIMIT

   将移除上面的定义。

9、处理器在识别标识符时,遵循与C相同的规则:标识符可以由大写字母、小写字母、数字和下划线字符组成,且首字符不能是数字。

10、条件编译:

1#ifdef #else#endif指令 

eg#ifdef MAVIS 

       #include “horse.h”//如果已经用#define定义了MAVIS,则执行下面的指令;

       #define TSTABLES 5

#else

       #include “cow.h”//如果没有用#define定义了MAVIS,则执行下面的指令;

       #define TSTABLES 15

#endif

注:#ifdef #else很想Cif  else。两者的区别是:预处理器不识别用于标记块的花括号({ }),因此它使用#ifdef(如果需要)和#else(必须存在)来标记指令块。

2#ifndef:与#ifdef指令的用法类似,也可以和#else #endif一起使用,但是他们的逻辑相反。#ifndef指令判断后面的标识符是否是未定义的,常用于定义之前的未定义的常量。

3#if#elif指令:和C语言中的if很像,#if后面跟整型常量表达式,如果表达式为非零,则表达式为真。可以按照if else的形式使用#elif

eg#if SYS==1        #include“ibmpc.h” #elif SYS==2    #include“vax.h” #elif SYS==3    #include“mac.h” #else    #include“general.h” #endif

11、预定义宏:

__DATE__:当前日期,一个以 "MMM DD YYYY" 格式表示的字符常量。

__TIME__:当前时间,一个以 "HH:MM:SS" 格式表示的字符常量。

__FILE__:这会包含当前文件名,一个字符串常量。

__LINE__:这会包含当前行号,一个十进制常量。

__STDC__:当编译器以 ANSI 标准编译时,则定义为 1

12、内联函数:(inline function):把函数变成内联函数建议尽可能快的调用该函数,其具体效果由实现定义。因此把函数变成内联函数,编译器可能会用内联代码替换函数调用,并(或)执行一些其他的优化,但是也可能不起作用。创建内联函数的定义有多种方法。最简单的方法是使用函数说明符inline和存储类别说明符staticeginline static void eatline()

13:数学库:包含许多有用的数学函数,math.h头文件提供这些函数的原型。

1double acos(double x) 返回以弧度表示的 x 的反余弦。

2double asin(double x) 返回以弧度表示的 x 的反正弦。

3double atan(double x) 返回以弧度表示的 x 的反正切。

4double atan2(double y, double x) 返回以弧度表示的 y/x 的反正切。y x 的值的符号决定了正确的象限。

5double cos(double x) 返回弧度角 x 的余弦。

6double cosh(double x) 返回 x 的双曲余弦。

7double sin(double x) 返回弧度角 x 的正弦。

8double sinh(double x) 返回 x 的双曲正弦。

9double tanh(double x) 返回 x 的双曲正切。

10double exp(double x) 返回x的指数函数的值(

11double frexp(double x, int *exponent) 把浮点数 x 分解成尾数和指数。返回值是尾数,并将指数存入 exponent 中。所得的值是 x = mantissa * 2 ^ exponent

12double ldexp(double x, int exponent) 返回 x 乘以 2 exponent 次幂。

13double log(double x) 返回 x 的自然对数(基数为 e 的对数)。

14double log10(double x) 返回 x 的常用对数(基数为 10 的对数)。

15double modf(double x, double *integer) 返回值为小数部分(小数点后的部分),并设置 integer 为整数部分。

16double pow(double x, double y) 返回 x y 次幂。

17double sqrt(double x) 返回 x 的平方根。

18double ceil(double x) 返回大于或等于 x 的最小的整数值。

19double fabs(double x) 返回 x 的绝对值。

20double floor(double x) 返回小于或等于 x 的最大的整数值。

21double fmod(double x, double y) 返回 x 除以 y 的余数。

14、可变参数:stdarg.h和变宏参功能类似。

1)提供一个使用省略号的函数原型;

2)在函数定义中创建一个va_list类型的原型;

3)用宏把该变量初始化为一个参数列表;

4)用宏访问参数列表;

5)用宏完成清理工作。

15、编程练习:16-5

#include <stdio.h> #include <stdlib.h> #include <time.h> void random_pick(int ar[], int arsize, int picks); #define SPOTS 51 #define PICKS 6 int main(void) {  int lotto[SPOTS];  int i;  char ch;  for (i = 0; i < SPOTS; i++)  lotto[i] = i + 1;  do {  random_pick(lotto, SPOTS, PICKS);  printf ("Again? <y/n> ");  ch = getchar();  while (getchar() != '\n')  continue;  } while (ch == 'y' || ch == 'Y');  puts ("Done");  return 0; } void random_pick(int ar[], int arsize, int picks) {  int i, index, temp;  srand((unsigned int) time(0));  if (picks > arsize)  {  fputs("Number of picks > array size\n", stderr);  fputs("Setting picks = array size\n", stderr);  picks = arsize;  }  for (i = 0; i < picks; i++)  {  index = rand() % (arsize - 1); /* pick a random element */  temp = ar[index];  printf ("%2d ", temp); /* display it */  if (i % 20 == 19)  putchar('\n');  ar[index] = ar[arsize - 1]; /* swap it with last element */  ar[arsize - 1] = temp;  arsize--; /* exclude end from search */  }  if (i % 20 != 0)  putchar('\n'); }

运行结果:

 

16、编程练习16-7

#include <stdio.h> #include <stdlib.h> #include <stdarg.h> void show_array(const double ar[], int n); double * new_d_array(int n, ...); int main() {  double * p1;  double * p2;  p1 = new_d_array(5, 1.2, 2.3, 3.4, 4.5, 5.6);  p2 = new_d_array(4, 100.0, 20.00, 8.08, -1890.0);  show_array(p1, 5);  show_array(p2, 4);  free(p1);  free(p2);  return 0; } void show_array(const double ar[], int n) {  int i;  for (i = 0; i < n; i++)  printf("%g ", ar[i]);  putchar('\n'); } double * new_d_array(int n, ...) {  va_list ap;  int i;  double * pt;  va_start(ap, n);  pt = (double *) malloc(n * sizeof(double));  for (i = 0; i< n; i++)  pt[i] = va_arg(ap, double);  va_end(ap);  return pt; }

运行结果:

 

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务