指针数组的每个存储区是一个指针类型的存储区,字符指针数组包含多个字符类型的指针,每个字符类型指针可以代表一个字符串.字符指针数组可以用来代表多个相关字符串,二维字符数组也可以用来记录多个相关字符串,通常采用字符指针数组记录多个相关字符串
/* * 字符指针数组演示 * */ #include <stdio.h> int main() { //char *strs[] = {"abc", "def", "xyz", //"iop", "vbn"}; char strs[][10] = {"abc", "def", "xyz", "iop", "vbn"}; int num = 0; for (num = 0;num <= 4;num++) { printf("%s ", strs[num]); } return 0; }
主函数的第二个参数是一个字符指针数组,其中每个指针代表一个字符串,这些字符串的内容来自于执行命令时输入的内容.主函数的第一个参数是整数类型的,它用来表示第二个参数里有效指针的个数
/* * 主函数参数练习 * */ #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int heads = 0, legs = 0, num = 0; if (argc < 3) { printf("命令错误 "); return 0; } heads = atoi(argv[1]); legs = atoi(argv[2]); for (num = 0;num <= heads;num++) { if (4 * num + 2 * (heads - num) == legs) { printf("兔子有%d只,鸡有%d只 ", num, heads - num); return 0; } } return 0; }
#define预处理指令可以用来定义宏,宏可以用来给数字起名字,定义宏的时候要把名称写在前面,名称代表的数字写在后面,宏名称通常只包含大写英文字母,宏名称里不可以有空格.用宏给数字起名字的时候不应该使用赋值操作符,编译器会把程序里的宏名称替换成它所代表的数字
/* * 宏演示 * */ #include <stdio.h> #define PI 3.14f #define CIRCLE(r) 2 * PI * r int main() { float pi = 3.14f; int radius = 0; printf("请输入半径:"); scanf("%d", &radius); printf("周长是%g ", CIRCLE(radius)); printf("周长是%g ", 2 * pi * radius); return 0; }
可以在编译命令里使用-D选项指定宏名称代表的数字
如果程序中有些数字只能在编译的时候才知道就可以采用宏代表它们
宏还可以用来给计算公式起名字,计算公式里包含未知数字,宏可以用参数表示这些未知数字
/* * 宏练习 * */ #include <stdio.h> #define SUB(x, y) x - y int main() { int num = 0, num1 = 0; printf("请输入两个数字:"); scanf("%d%d", &num, &num1); printf("相减结果是%d ", SUB(num, num1)); return 0; }
计算机采用二次替换的方式处理带参数的宏
宏的参数可以不代表数字,它没有类型名称
/* * 宏演示 * */ #include <stdio.h> #define SUB(x, y) ((x) - (y)) int main() { printf("SUB(10, 5)是%d ", SUB(10, 5)); printf("20 - SUB(10, 5)是%d ", 20 - SUB(10, 5)); printf("SUB(20, 10 - 5)是%d ", SUB(20, 10 - 5)); return 0; }
如果宏有多个参数就应该在小括号里写多个参数名称,相邻的参数名称之间用逗号分开
宏不能使用自己的存储区和函数之间进行数据传递,宏没有形式参数也没有用来存放返回值的存储区
能当作数字使用的宏必须编写成表达式(因为宏没有用来记录返回值的存储区的)
宏的参数可以直接代表函数的存储区,对宏参数内容的修改就是对函数存储区内容的修改(因为宏没有形式参数)
因为宏没有用来存放返回值的存储区,所以不能保证优先计算宏里面的操作符,所有能当作数字使用的宏都必须写在小括号里面
/* * 宏练习 * */ #include <stdio.h> #define SQUARE(n) ((n) * (n)) int main() { int num = 5; printf("SQUARE(5)是%d ", SQUARE(5)); printf("SQUARE(++num)是%d ", SQUARE(++num)); return 0; }
宏没有形式参数所以不能保证优先计算参数里面的操作符,编写宏的时候应该把所有能当作数字使用的参数都写在小括号里
不要把自增或自减的结果作为宏的参数使用
编写宏的时候可以使用一些特殊的符号,它们叫做宏操作符
#是一个宏操作符,它可以把宏的参数转换成字符串字面值
##也是一个宏操作符,它可以把一个代表标识符的参数和其他内容连接得到一个新的标识符
/* * 宏操作符演示 * */ #include <stdio.h> #define STR(n) #n #define PTR(n) p_##n int main() { int num = 0; int *PTR(num) = # STR(2 + 3); return 0; }
条件编译可以在编译时从几组语句里选择一组编译而忽略其他组
#ifdef/#ifndef...#else...#endif
这个结构可以根据一个宏名称是否被定义过从两组语句里选择一组编译.最开始的预处理指令要从两个里选择一个,不论选择哪个后面都要写一个宏名称.如果选择#ifdef就表示它后面的宏名称被定义过的时候编译前一组语句,否则编译后一组语句,如果选择#ifndef就和#ifdef刚好相反
/* * 条件编译演示 * */ #include <stdio.h> int main() { //#ifdef YI #ifndef ER printf("1 "); #else printf("2 "); #endif return 0; }
#if...#elif(任意多次)...#else...#endif
以上结构也可以实现条件编译,它可以根据任意逻辑表达式从多组语句中选择一组编译
/* * 条件编译练习 * */ #include <stdio.h> int main() { int order = 0; printf("请点菜:"); scanf("%d", &order); #ifdef ZHAOBENSHAN if (order == 1) { printf("没有 "); } else { printf("真没有 "); } #else if (order == 1) { printf("有 "); } else { printf("没有 "); } #endif return 0; }