0、基本知识
基本数据类型
char、short( int)、int、long( int)、long long (int)、float、double、long doulbe,括号内内容表示可省略。除了上述几种外,前5中还有对应的unsigned类型。3u、3ul、1.2f、1.2L。
常量:整型常量、浮点型常量、符号常量(用#define定义)、字符常量、字符串常量、枚举常量
字符常量中有一些比较特别,成为转义字符,ANSI C中的全部转义字符序列如下:
\a 响铃符 \\ 反斜杠
\b 回退符 \? 问号
\f 换页符 \' 单引号
\n换行符 \" 双引号
\r 回车符 \ooo八进制数,ooo代表1~3个八进制数字(0~7)
\t 横向制表符 \xhh 十六进制数,hh为一或多个十六进制数字(0~9,a~f,A~F)
\v 纵向制表符 \0
运算符优先级及结合性:
函数与程序结构
如果函数中省略了返回值类型,则默认为int类型。
函数间的通信可以通过参数、返回值、外部变量进行。
1、struct与typedef struct
struct Student{int a;int b}stu1; //定义名为Student的结构体,及一个Student变量stu1
struct {int a;int b;}stu1; //只定义了一个结构体变量stu1,未定义结构体名,无法再定义其他变量
typedef struct Student{int a;int b;}Stu1,Stu2; //定义结构体类型为Student,别名为Stu1或Stu2,此时有三种定义相应变量的方式:
struct Student st; 或 Stu1 st; 或 Stu2 st;
typedef struct{int a;int b;}Stu1,Stu2; //未指定结构体类型名,但给了别名Stu1或Stu2,可用之定义变量
2、struct 内存空间分配原则 http://zhidao.baidu.com/link?url=bWqgw8n8ck6zBwaYAzeBOcAFM7ZIErMtYz8XznIyLcoid9tZkw_5LlOz0JQg5othMWEVXeHOj557KRu3gaxVeK
原则1、数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)
原则2、结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储)
原则3、收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。
获取结构体成员在结构体内的偏移量:(将0强制转换成这个结构体的指针,来访问这个结构体中的成员,然后,取这个成员的地址,得到的就是成员相对结构体起始的偏移)
1 #define OFFSET(type, field) (&((type *)0)->field) 2 3 struct Node { 4 int a; 5 char b; 6 short c; 7 char *d; 8 }; 9 10 int main(int argc, char *argv[]) 11 { 12 printf("%p\n", OFFSET(struct Node, a)); 13 printf("%p\n", OFFSET(struct Node, b)); 14 printf("%p\n", OFFSET(struct Node, c)); 15 printf("%p\n", OFFSET(struct Node, d)); 16 return 0; 17 }
3、typedef struct node{int a; struct node*lchild; struct node* rchild;}BNode,*BTree;
这里:
BNode为struct node 的别名,相当于 typedef struct node BNode
BTree为struct node*的别名,相当于typedef struct node* BTree
4、*p++,(*p)++,*++p
char data[100]={'c','x'}; char *p=data;
printf("%c\n",*p++);//c printf("%c\n",*p);//x printf("%s\n",data);//cx
printf("%c\n",(*p)++);//c printf("%c\n",*p);//d printf("%s\n",data);//dx
printf("%c\n",*++p);//x printf("%c\n",*p);//x printf("%s\n",data);//cx
5、中缀表达式转后缀表达式:
手算:
用手算的方式来计算后序式相当的简单,将运算子两旁的操作数依先后顺序全括号起来,然后将所有的右括号取代为左边最接近的运算子(从最内层括号开始),最后去掉所有的左括号就可以完成后序表示式,例如:
a+b*d+c/d => ((a+(b*d))+(c/d)) -> abd*+cd/+
中缀转前缀类似
计算机算:用堆栈
6、C/C++中的 a和&a
#include <stdio.h> int main(void) { int a[5] = {1,2,3,4,5}; int *ptr = (int *)(&a + 1); int temp1 = *( a + 1 );//2 int temp2 = *( ptr - 1 );5 return 1; } &为取址运算符,&a得到a类型的指针;对指针进行加1操作,得到的是下一个元素的地址,而不是原有地址值直接加1.所以,一个类型为T的指针的移动,以sizeof(T)为移动单位。 &a + 1:取数组a的首地址,该地址的值加上sizeof(a)的值,即&a +5* sizeof(int),也就是下一个数组的首地址,显然当前指针已经越过了数组的界限。 *(a + 1):a和&a的值是一样的,但是意思是不一样的:a是数组首元素的首地址,也就是a[0]的首地址,&a是数组的首地址。a + 1是数组下一个元素的首地址即a[1]的首地址;&a + 1 是下一个数组的首地址 *(ptr - 1)因为ptr指向的是a[5],并且ptr是int *类型,所以*(ptr - 1)是指向a[4]
7、预处理的妙用
#define swap(type, i, j) {type t = i; i = j; j = t; int main() { int a = 23, b = 47; printf("Before swap. a: %d, b: %d\n", a, b); swap(int, a, b) printf("After swap. a: %d, b: %d\n", a, b); return 0; }
8、关于swap,C中可以通过指针实现,C++中除了用指针外,还可以通过引用&实现
方式一:如同C语言使用指针。 方式二:使用“引用”(&) void swap(int& i, int& j) { int t = i; i = j; j = t; } C++的函数参数使用引用(&),值通过引用传递(pass by reference),函数中的参数不被 copy(如果传的是类就不会调用拷贝构造函数),所以在函数中能正确交换两个变量的值。
另,不用临时变量的swap实现方法:
//利用异或运算 void swap(int &x,int &y) { x^=y; y^=x; x^=y; } //利用加减 void swap(int &x,int &y) { x+=y; y=x-y; x-=y; }