1标准输入输出头文件的意义?以及main函数的作用?
<>系统头文件、””自定义头文件。引入系统的标准头文件,可以用其中的一些函数,如printf();
main函数是C语言程序的入口(开始执行的位置),{}表示main函数的起止点
2怎样理解注释增强代码的可读性和可维护性?
//、/**/对代码的解释说明
3C语言中有哪些基本的数据类型,占的字节数,以及格式化的描述形式?
char 、signed char 、unsigned char 、bool 1 %c
short 、unsigned short 2 %hd
int 、float 、unsigned int 4 %d 、%f
double、 long int 、unsigned long 8 %lf 、%ld
sizeof(数据类型名) 求某种类型的字节数
4变量的本质,变量的命名规则,以及变量初始化的方式?
本质:内存里的存储单元。开辟空间、往空间里面写内容、从空间里面读取内容
命名规则:每个变量必须以字母和下划线开头,由字母下划线数字组成
大小写是两个不同的字符
不能用C的关键字做变量名
初始化:声明同时进行初始化、先声明然后在运行时使用赋值表达式初始化、先声明然后用户输入数值进行初始化
5什么是常量,它的意义?
在变量前面加上const关键字,成为常量。
常量的值必须在创建的同时初始化,且一经初始化就不能改变
6怎样声明一个枚举类型,如何使用,枚举如何代替宏定义?
enum weekday {Mon, Tue, Wed,Thr, Fri, Sat, Sun } a, b, c;
enum 关键字,weekday枚举名,a,b,c 枚举变量名
{ , ,}表示这种类型可能取的值,每个值对应一个整数,从0开始,依次加1;
1、enum weekday
{
…
}; //没有定义变量
enum weekday a, b, c; //可以用这种方法定义
2、enum weekday
{
…
}a,b,c; //可以增加e, f, g等变量
3、enum
{
…
}a, b, c; //没有枚举类型名,只能有abc三个变量
{ ,}表示这种类型可能取的值,每个值对应一个整数,从0开始,依次加1;
可以代替整型的宏定义,增强代码可维护性;
枚举是封装好的define集合,用便于记忆的字符来代表常量,枚举类型实质是整型变量,通过枚举类型将一类有关联的标识组合起来,增加程序的可读性和可维护性
枚举变量可以用在switch语句中作为常量使用;使用枚举变量时,应该把枚举变量的值赋值为枚举中常量集合中某个常量的值
7定义初始化一个数组,用下标访问数组
int a[5];
int a[ ]={1, 2, 3, 4};
int a[5]={1, 2, 3, 4};
8大数分解
万 12345/10000
千 12345/1000%10 == 12345%10000/1000
百 12345/100%10 == 12345%1000/100
十 12345/10%10 == 12345%100/10
个 12345%10
9 怎么样理解前置(后置)自增自减?
当需要使用自增自减的值时,考虑其是前置还是后置
前置:++i 先进行自增自减,再使用增减后的值
后置:i-- 先使用变量当前的值,然后再进行自增自减运算
10怎样使用&& ||?
与、全真为真,有假则假
或、全假为假,有真则真
非、非真为假,非假为真
11条件表达式
if()
…
else if ()
…
else
…
12隐式和显示类型转化?
当某一个操作符拥有不同类型的操作数时,将发生类型转换
显式:(数据类型名) 变量名 float i = 1.23; int j = (int) i;
i的类型依然是float,只是把i的整数部分赋给了j
隐式:char c = ‘a’; int i = c;
赋值表达式,把等号右边的类型,转型为等号左边的类型;
在一个表达式中,默认状态下变量是从低类型向高类型转化的
13控制流
顺序结构:按照语句编写的顺序顺序执行
;是语句结束的标志;{}被用在程序块中,其右侧括号后面不加分号;任何可以放置单个语句的地方,都可以用一个复合语句来代替
选择结构:if:条件为真时,执行语句,否则跳过不执行
if-else:条件为真时执行if分支语句,否则执行else分支语句(嵌套)
switch:根据条件表达式的值,执行多个动作当中的某一个动作
switch (…) //表达式或者变量,必须返回整数型(包括字符型)
{
case 1: …;break; case:… 必须是常量表达式,且不允许重复
case 2: …;break;
default: …; break;
}
循环结构:while:首先初始化循环控制变量while(…//条件为真) {…//进入循环体;改变循环控制变量}
do/while:后置测试循环,先循环一次,再测试条件 do{…循环体;修改循环控制变量}while (表达式)//控制变量不需要初始化
for:前置测试循环,先测试条件是否满足,若满足再进入循环体执行 for(循环控制变量初始化;条件表达式,为真则执行循环体语句;修改循环控制变量) {…循环体语句} à首先初始化循环控制变量,然后执行条件表达式,为真则执行循环体语句,然后改变循环控制变量,再执行条件表达式,为真则执行循环体语句。。。直到条件表达式为假
14break,continue, return作用?
break:结束循环,执行循环后面的语句;多层循环只跳出break所在这一层循环;跳出switch结构
continue:跳过本次循环而执行下次循环
return:退出该函数的执行(跳出函数)
15函数作用
可以多人合作开发
单元测试,有利于早发现bug
复用性
16怎样封装函数,函数调用的实质;
封装函数:main.c中需包含自定义的调用函数的头文件;调用函数头文件声明调用函数原型;调用函数.c文件定义、实现调用函数
实质:
17函数的值传递
传值方式,在函数调用时,把实参值的一份拷贝赋值给形参
在被调用函数体内,操作和修改的是形参的值,实参的值不受影响
单向传递,从实参到形参
18指针实质,指针访问变量,指针的类型,野指针,空指针,手动开辟内存空间
指针也是一个变量,它的值是另外一个变量的地址,即指针是存放内存地址的变量
指针类型与它指向的变量的类型保持一致
char *p = &achar; //p指针变量名;*表示p是一个指针变量;&取地址运算符,返回变量地址;char*指针变量的类型,p是一个字符型指针,char代表指针指向的变量的类型;%p打印地址,打印指针变量的值;指针是long int,8个字节
解引用运算符,*p:放等号右边,读取p指向的变量的值;左边,给p指向的变量写入内容
如果定义一个指针没有初始化,它存储的是垃圾地址,即为野指针
当定义一个指针还不确定指向哪个变量,就把它置为空,空指针是被初始化为NULL的指针,里面的地址是0(不要解引用空指针,因0号地址属于系统级内存空间,不允许用户级程序访问)
int * p = (int *) malloc(sizeof(int));
free(p);
19传地址,传指针,返回指向局部变量的指针(解决方案),函数返回值
int exchange(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int aa=1,bb=2;
指针int p = &aa, *q = &bb;
指针exchange(p, q);
地址exchange(&aa, &bb);
printf(“..”);
}
111、定义全局变量*p,开辟堆空间,主函数回收开辟的堆上的内存空间
#include <stdio.h>
#include <stdlib.h>
int *p=NULL;
int *Test()
{
p=(int *)malloc(sizeof(int));
*p=10;
return p;
}
int main()
{
int c=*Test();
printf("%d\n",c);
free(p);
return 0;
}
222、static
#include <stdio.h>
int *Test()
{
static int temp=12; //加static定义到静态存储区,不加则声明局部变量,调用函数结束时内存回收
return &temp; //不能返回一个指向局部变量的指针
}
int main()
{
int c=*Test();
printf("%d\n",c);
return 0;
}
20内存分配问题
逐步分析
全局变量:在所有函数体之外声明的变量,作用于所有源文件,全局区
静态全局变量:不可用于其他文件
静态局部变量
局部变量:栈(形参放在栈上)
堆:手动开辟的内存空间
静态存储区:变量前加static,生命周期很长,从申请到程序退出
21怎样用指针访问数组?
数组元素在内存空间中连续分布,每个元素有相应的内存地址;数组名就是数组首地址,就是指向数组首元素的指针,即a == &a[0];数组名是个指针常量,存储的地址是不能更改的
p = a; 或 p = &a[0]; 则a[1]==*(p+1);
22指针运算和数组?
#include <stdio.h>
int main()
{
char a[8];
int b[8];
float c[8];
char *pa = a + 1;
int *pb = b + 4;
float *pc = c +6;
printf("%p,%p\n",a,pa);
printf("%p,%p\n",b,pb);
printf("%p,%p\n",c,pc);
printf("%ld,%ld,%ld\n",pa-a,pb-b,pc-c); //1,4,6
printf("%ld,%ld,%ld\n",sizeof(pa-a),sizeof(pb-b),sizeof(pc-c)); //8,8,8
return 0;
}
23指针常量的使用
#include <stdio.h>
int main ()
{
const int a=9;//常量,定义时要初始化
//a=9; 常量初始化后不能修改,即使赋相同的值也不行
const int aa = 99;
int b = 10;
int c = 11;
//int pp=&b;
int * const p = &b;
//p=pp; 指针常量初始化后不能修改,即使赋相同的值也不行
//p=&c; 不同的值更不行
printf("%d\n",*p);
const int *q = &a; //指向常量的指针,这个指针最好要指向一个常量
q= &b; //也可以指向变量
printf("%d\n",*q);
q=&aa; //指向常量的指针,也可以指向其他常量
printf("%d\n",*q);
return 0;
}
int* const p = &a; //必须在声明时初始化,且指针常量的值不能再修改,即不能存一个新的地址,不能指向别的变量,但是可以通过指针常量修改它所指向的变量的值
24指向常量指针的使用?
const int a = 1;
const int *q = &a; //指向常量的指针,这个指针指向一个常量
q = &b; //也可以指向变量或者其他常量
25全局变量,函数域,块域
标识符:变量名、函数名
作用域:能够访问某标识符的程序段
全局变量:在所有函数体之外声明的变量,作用于所有源文件,全局区
局部变量
函数域:标识符只能在它所在的函数被访问到
函数形参:函数实现时形参的名字可以和函数原型形参名字不同;但类型要一致。函数原型的形参的作用域,只限于函数原型本身
块域:被大括号{}包围的范围叫块;其作用域:从标识符开始到块结束,可以被识别
当在块内部声明了一个与外部标识符同名的标识符时,外部标识符可以被临时隐藏
就近原则:若有同名标识符,优先使用同一作用域内的标识符
如果想访问被临时隐藏的全局变量,要使用全局域操作符::
26链接编译理解
预处理 编译 链接
预处理阶段,编译器以C文件作为一个单元,首先读这个C文件,发现包含头文件,就会在所有搜索路径中寻找文件,找到之后,就会将相应头文件中再去处理宏,变量,函数声明,嵌套的头文件包含等,检测依赖关系,进行宏替换,看是否有重复定义与声明的情况发生,最后将那些文件中全部扫描进这个当前的C文件中,形成一个中间"C文件"
编译阶段,将中间C文件的所有变量,函数分配空间,将各个函数编译成二进制码,按照特定目标文件格式生成目标文件,在这种格式的目标文件中进行各个全局变量,函数的符号描述,将这些二进制码按照一定的标准组织成一个目标文件
连接阶段,将上一步生成的各个目标文件,根据一些参数,连接生成最终的可执行文件,主要的工作就是重定位各个目标文件的函数,变量等,相当于将个目标文件中的二进制码按一定的规范合到一个文件中
想在多个文件中访问一个变量,就要在变量前面加上extern关键字
27怎样使用函数指针
函数指针的类型就是指针指向的函数的参数类型和返回值类型
int ( *fp) (int a, intb); //声明一个函数指针
int func (int m, intn); //声明一个函数
fp = func; 或 fp = &func;
28字符串和字符数组的区别
字符串:用双引号包围 “abcde”
字符数组:数组的每一个元素都是字符,字符用单引号包围
在内存里用字符数组存储字符串,字符数组要加一个元素,以空字符\0作为结尾
定义:字符串就是存入字符的数组,以’\0’作为结束标志,%s输出
区别:字符串用字符数组存储,但是字符数组不需要有结束标志’\0’,字符串需要
29怎样拷贝一个存在静态常量区的字符串
char c[6] = “hello”; //声明之后,首先在静态存储区的常量区开辟一块空间,写入hello,然后开辟一块连续的栈空间,把字符串拷贝一份,然后将内容写入到栈空间,c本身是个变量,所以可以通过c修改他所指向的内存的值
可以把一个字符串赋值给一个char * 类型的指针,但不能通过指针修改这个字符串
char *str = "I am astudent";
//const char *str = "Iam a student";
//把一个字符串赋给一个字符指针,相当于赋给一个指向字符常量的指针
str = "sun"; //可以,改变地址,指向sun
//strcpy(str,"abcde");//错误,改变值
30使用strcpy strcmp strcatstrlen等字符串函数的操作
strlen (length) 返回字符串的字符数(长度),不包括\0
strcat (to, from) ,把from”…”连接到to”…”的结尾
strcpy (to, from) ,把from”…”copy到to”…”
strcmp (s1, s2) s1 > s2,返回正数s1 < s2,返回负数s1 = s2,返回0
两个字符串从前到后,逐个比较每对字符的ASCII码的大小;若相同,则继续比较,直到遇到第一对不同的字符,ASCII码整数大的字符为大
31 起别名的语法规范
typedef type IDENTIFIER 关键字 已有类型 类型别名,一般全大写字母
typedef unsigned int UN;
用来代替自定义的枚举类型、结构体类型、系统定义的长度较长的类型
32 声明结构体类型的变量的两种主要形式,以及初始化
//111
struct //直接定义结构体变量,结构体本身没有名字
{
char name[15];
int num;
int age;
}Astu; //结构体变量的声明,必须紧跟在结构体定义的后面
//222
struct student //结构体类型,类型名为struct student
{
char name[15];
int num;
int age;
}Bstu; //可以在这里声明结构体变量
struct student Cstu; //也可以用结构体类型名,声明一个结构体变量
//333
typedef struct //给结构体类型起一个别名 STU
{
char name[15];
int num;
int age;
}STU; //结构体别名
STU Dstu; //通过别名,声明结构体变量
>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<
STU Dstu = {…, …, …};
33 结构体类型的指针访问结构体类型的变量
访问:p = &Astu; Astu.name p -> num (*p).age
34 如何计算结构体类型的变量在系统内存里占用的字节数
结构体的值从上往下依次分配,先找到最大字节的变量,然后依次从上到下分配内存,当分配到相应类型时,图中编号一定要能整除当前类型字节数。(大小要能被每一种类型大小整除)
char a[10]; //0—9
int b; //12—15
char c; //16
double a; //24—31
double 最大,8字节,以8字节为单位画内存分配:
0 1 2 3 4 5 6 7
8 9 10 11 12 13 14 15
16 17 18 19 20 21 22 23
24 25 26 27 28 29 30 31
<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>><<<<<<<>>>>>>>>>
int a; //0—3
fioat b; //4—7
char c[15]; //8—22
0 1 2 3
4 5 6 7
8 9 1011
12 13 14 15
16 17 18 19
20 21 22 23
24 25 26 27
35宏替换
#define N 10 //预处理阶段,源代码里所有的N将被替换成10
#define max(a,b) ((a) >(b) ? (a) : (b)) //宏替换的参数都要加上括号
#define exchange ( x, y)\
{\
int temp = *x;\
*x = *y;\
*y = temp;\
} //替换自定义函数,除最后大括号的结束行,其余的都要加上”\”
36条件包含
#if 。。。 //如果为真,则包含后面内容,直到#endif、#elif、#else结束
#ifndef XXX
#define XXX
……
#endif //避免重复定义同一个头文件
#ifdef XXX //如果宏定义了XXX,执行下面语句
……
#else //否则,执行else下面语句
……
#endif
#ifndef XXX //如果没有宏定义XXX,执行下面语句
……
#else //否则,执行else下面语句
……
#endif