C语言部分知识

来源:互联网 发布:使命召唤11和12的优化 编辑:程序博客网 时间:2024/04/28 20:41

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(循环控制变量初始化;条件表达式,为真则执行循环体语句;修改循环控制变量)   {…循环体语句}  à首先初始化循环控制变量,然后执行条件表达式,为真则执行循环体语句,然后改变循环控制变量,再执行条件表达式,为真则执行循环体语句。。。直到条件表达式为假

14breakcontinue 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;

}

222static

#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

0 0
原创粉丝点击