1.引言
作为天朝的软件工程专业的大学生,我大学时的经历和大多数的其他同学大都一样,逃课、打游戏是家常便饭,所以毕业快两年了,依然对最初的C语言有些部分不清不楚,对于现在的C++应用也造成了一定的困惑。最近痛定思痛,决定重新拜读一下谭老爷子的大作(本人不才,虽然知道谭老师的书并不是C的标准,有好多地方值得商榷,但是从实用性上来讲,还比较适合我这个菜鸟学习),将经常用到和易混淆的东西列出来,供大家和自己参考。
2.字符和字符串(不包括指针)
这部分共分为三个模块
2.1 字符常量:
形象一些,就是‘a’,‘b’,‘?’,'\n'这等特征的常量,只能用单引号来做标识符
2.2 字符变量:
举个例子:
char b;
b = 'b';
b = b- 32;
上面例子说明、引申了几个问题:
(1)b 就是字符变量(第一行)
(2)字符变量可以由字符常量进行赋值(第二行)
(3)字符变量也可以由整形变量进行赋值(第三行)
(4)字符变量可以和整形变量之间做加减法(第三行)
(5)在Turbo C 中,字符变量在内存中占一个字节,整形变量占两个字节
(6)之所以字符变量可以和整形变量之间直接运算,原因是字符变量在内存中是被翻译成ASCII码的,ASCII码刚好就是由整形进行表示的
(7)ASCII码有固定的范围大小(0-255),刚好符合字符变量一个字节的存储
2.3 字符串常量:
(1)可以有一个或多个字符,其形式就是:"I Love China" 或者 "I"
(2)字符串常量在内存中存储时,在字符串常量的末尾添加一个'\0',其ASCII码的值为0
(3)字符串常量可以用字符数组来存储
(4)C语言中没有字符串变量
2.4 附上Turbo C 下的一些实用工具图
3.数组(不包含指针)
这部分共分为三个模块,不说废话,不和指针结合,数组没有任何难度
3.1 一维数组
int a[3] = {4,5,6};
3.2 二维数组
int b[2][3] = {{1,2,3},{4,5,6}};
3.3 字符数组
char c[10]={‘c’, ‘ ’, ‘p’, ‘r’, ‘o’, ‘g’, ‘r’, ‘a’,’m’};
当把一个字符串存入一个数组时,也把结束符'\0'存入数组,并以此作为该字符串是否结束的标志。
4.函数
4.1用户存储区空间示意图
![](https://img-my.csdn.net/uploads/201301/17/1358407418_2914.jpg)
4.2 变量类型
4.2.1 全局变量(外部变量)
(1)在函数的外部进行定义的变量
(2)全局变量一定是静态存储,所以要给初值
(3)如果全局变量不在文件的开头定义,而在定义点之前的函数想引用该变量,则应该在引用之前用关键字extern对该变量作“外部变量声明”。
4.2.2 局部变量
4.2.2.1 动态变量
(1)如果在定义的时候没有初始化,那么初值是不确定的
(2)可以定义为寄存器变量
4.2.2.2 静态变量
(1)用 static 进行修饰
(2)如果在定义的时候没有初始化,编译器会给默认的初值(int 型的给0)
(3)不能定义为寄存器变量
4.2.3 寄存器变量
(1)只有动态的局部变量和形式参数可以设置为寄存器变量
(2)代码:
int fac(int n)
{register int i,f=1;
for(i=1;i<=n;i++)
f=f*i
return(f);
}
main()
{int i;
for(i=0;i<=5;i++)
printf("%d!=%d\n",i,fac(i));
}
5.预处理命令
5.1 宏定义
#define M (y*y+3*y) //不带参数的
#define M(y) y*y+3*y //带参数的
5.2 文件包含
#include"stdio.h"
5.3 条件编译
5.3.1 第一种
#define NUM ok
main(){
struct stu
{
int num;
char *name;
char sex;
float score;
} *ps;
ps=(struct stu*)malloc(sizeof(struct stu));
ps->num=102;
ps->name="Zhang ping";
ps->sex='M';
ps->score=62.5;
#ifdef NUM
printf("Number=%d\nScore=%f\n",ps->num,ps->score);
#else
printf("Name=%s\nSex=%c\n",ps->name,ps->sex);
#endif
free(ps);
}
5.3.2 第二种
#ifndef 标识符
程序段1
#else
程序段2
#endif
5.3.3 第三种
#define R 1
main(){
float c,r,s;
printf ("input a number: ");
scanf("%f",&c);
#if R
r=3.14159*c*c;
printf("area of round is: %f\n",r);
#else
s=c*c;
printf("area of square is: %f\n",s);
#endif
}
6.指针(重点在于:指针、数组和字符串结合进行分析)
6.1 指针概念(指针和指针变量)
6.1.1 例子
int a[3] = {1,2,3};
int* p = &a[0];
6.1.2 指针
(1)指针就是地址(指针 = 地址)
(2)&a[0] 的值就是指针
6.1.3 指针变量:
(1)指针变量:用来存储指针(地址)的变量
(2)p 就是指针变量
6.2 指针与数组(一维数组和二维数组)
6.2.1 一维数组:记住以下四点即可
(1)数组名为首地址
(2)用 ‘&’ 符号取地址
(3)用 ’*‘ 符号取数组元素的值
(4)指针的加减标记着数组的位置
看代码:
int a[3] = {1,2,3};
int* p0 = &a[0];
int* p1 = a + 1;
//地址:(1)a为数组的首地址
// (2)&a[i]为第i个数组元素的地址
// (3)a+i 为第i个数组元素的地址
// (3)p++、p--、p+i、p-i等可以指向数组的任意位置
// 值:(1)*a、a[0]为数组的首个元素值
// (2)a[i]为第i个数组元素的值
// (3)*(a+i)为第i个数组元素的值
// (4)*(p++)等为某个数组元素的值
6.2.2 二维数组:
(1)在这个地方,是谭书争议最大的地方,很多人会有不理解(包括本人在内),但是可以肯定的一点是,书中给出的结果是绝对正确的,针对这一块我会在以下给出代码调试的证据
(2)对于 a[i][j] 来说:
int b[2][3] = {{1,2,3},{4,5,6}};
//int* p0 = b;//这个地址不能给指针变量赋值,编译器会报错,对比可以赋值的两个来说,只是变量类型不同
int* p1 = b[0];
//int* p2 = b + 1;//这个地址不能给指针变量赋值,编译器会报错,对比可以赋值的两个来说,只是变量类型不同
int* p3 = *(b + 1);
// (1)b是二维数组的首地址;是第0个一维数组的首地址;
/(2)(3)(4)的争议很大,但是从调试结果来看,没有错,所以死记住
// (2)b[i] 是二维数组的第i个一维数组的首地址;
// (3)b + i 是二维数组的第i个一维数组的首地址;
// (4)*(b + i)是二维数组的第i个一维数组的首地址;
// (5)*(b + i)+ j 是二维数组的第i行,第j列的地址;
// (6)*(*(b + i)+ j) 是二维数组的第i行,第j列的元素值;
// 有人把*号说成是二维数组由行变列的标志,还有人说成是数组降级的标志,无论如何,死记住就好
// 谭书中的描述不是标准C,所以一定死记住,将来接触了标准C之后再回来骂我,我只是帮你记住
没图说个jb,上图
![](https://img-my.csdn.net/uploads/201301/17/1358414108_8770.jpg)
6.3 指针与字符串
6.3.1 字符串的表示形式
(1)用数组存放字符串
main(){
char string[]={”I love China!”};
printf("%s\n",string);
}
(2)用字符串指针指向一个字符串
main(){
char *string=”I love China!”;
printf("%s\n",string);
}
6.4 指针,数组、字符串之间的关系一览
6.4.1 代码
char string[]={”I love China!”};//字符串向数组的转变
char* string=”I love China!”;//字符串向指针的转变
char* string = string;//数组向指针的转变
6.5 指向指针的指针变量
(1)指向指针的指针变量:存储指向指针型数据的指针
用一个例子说明
main()
{char *name[]={"Follow me","BASIC","Great Wall","FORTRAN","Computer desighn"};
char **p;
int i;
for(i=0;i<5;i++)
{p=name+i;
printf("%s\n",*p);
}
}
6.6 常用的指针含义图解
6.7 void类型指针,在C++中很常见
(1)void* a;
(2)是ANSI新标准增加的一种指针类型,即可以定义一个指针变量,但不指定它是指向哪一种类型数据。