字符串
c中没有类似java的字符串类型
用一个一维的char数组来存字符串, 尾部必须有一个空字符(‘\0’)来作为结束:
|
|
指针
指针用来指向一块内存地址。如:int a = 10; int p = &a; int c = p;
字符串指针:
char p = “admin”, char q = p; char q = p; 与 char q = &p[0]; 效果一样的(数组的首元素地址就是该数组的地址) 。 而 char *q=&p[1]; 打印q, 输出:”dmin”
遍历:
123for (; *p != '\0'; p++) {printf("=%c ", *p);}
当使用指针遍历后,这时地址位已经移到结束符的位置了。所以想重置时,需要 p -= 5;
交换字符:
|
|
- 交换字符串:
|
|
指针和数组的互换
形参数组,实参指针
|
|
形参指针,实参数组
|
|
错误使用举例
首先要牢记一点,指针表示一个内存地址。
char *a = "stone";*a = "aaa"; //error
a 表示 a指向的值,而字符串就是一组字符序列,所以实际 a指代的是字符数组a 的首位的值
简单的说: 不能将一个常量值,赋给另一个常量
正确的写法:a = "aaa";
//将常量赋给变量
- 12char b[] = "stone";b = "aaaa"; //error
这里 b 还是指代的字符数组的首地址。 参照上面的遍历 来理解。
正确代码,需要用一个临时的指针变量:
12char *p = b;p = "aaaa"; //fine 计算数组的长度。
12int a[4] = {1, 2, 3, 4};int len = sizeof(a) / sizeof(int);如上,能得出一个正确的值。
但,若是将该数组传递到一个函数里,再进行计算可能就有问题了
123void calc_len(int *p) {int len = sizeof(p) / sizeof(int); //p表示地址 len=2}解决方法:在外部计算好数组长度,再传递给函数。
返回指针的函数
返回指针的函数的一般形式为:类型名 *函数名(参数列表)
|
|
指向函数的指针
定义的一般形式:函数的返回值类型(*指针变量名)(形参1, 形参2,...) = 函数名;
|
|
将函数指针作为形参
|
|
预处理指令
C语言在对源程序进行编译之前,会先对一些特殊的预处理指令作解释(比如#include文件包含指令),产生一个新的源程序(这个过程称为编译预处理),之后再进行通常的编译
预处理指令可以出现在程序的任何位置,它的作用范围是从它出现的位置到文件尾。
宏
#define
用来定义一个宏
不带参数的宏定义
格式:define 宏名 字符串
, 如define ABC 10
右边的字符串也可以省略,比如#define ABC
它的作用是在编译预处理时,将源程序中所有”宏名”替换成右边的”字符串”,常用来定义常量
宏名的有效范围是从定义位置到文件结束。如果需要终止宏定义的作用域,可以用#undef ABC命令
省略右边字符串的宏, 主要用于 『条件编译』指令中
带参数的宏定义:宏函数
格式:define 宏名(参数列表) 字符串
注意:宏名和参数列表间不能有空格
在编译预处理时,将源程序中所有宏名替换成字符串,并且将 字符串中的参数用 宏名右边参数列表中的参数替换
|
|
引用已经定义的宏名
|
条件编译
程序的其中一部分代码只有在满足一定条件时才进行编译,
否则不参与编译(只有参与编译的代码最终才能被执行),这就是条件编译
语法格式:
|
|
一般用来判断宏或常量, 不能判断 非预编译 的 运行时 变量。 例:
|
|
判断是否定义过宏:
|
|
文件包含指令
第1种形式#include<文件名>
直接到C语言库函数头文件所在的目录中寻找文件
|
第2种形式#include”文件名”
这种形式下,系统会先在源程序当前目录下寻找,若找不到,再到操作系统的path路径中查找,最后才到C语言库函数头文件所在目录中查找
注意:#include指令允许嵌套包含,比如a.h包含b.h,b.h包含c.h,
但是不允许递归包含,比如 a.h 包含 b.h,b.h包含 a.h
使用#include指令可能导致多次包含同一个头文件,降低编译效率
解决方法:在包含的文件里,加上条件编译指令,防止函数被重复定义, 如:
|
|
C中没有类似java的package的概念,它只有文件系统。
如果要引入当前目录下的文件夹util中的calcUtil.h :
#include "calcUtil.h"