C语言知识总结(建议收藏)

目录

一、数据类型

1.基本的数据类型

2.变量的定义格式是什么?给变量复制有几种方式?

3.定义一个变量 ,向变量写入10

4.使用const定义的变量有什么特点? 

5. 数据在内存中是怎么存储的?数据溢出会发生什么事情?

6.什么是源码、补码、反码? 

7.char a=200;在内存中怎么存储的? 

8.sizeof的作用是什么?该怎么使用? 

9.说一说printf函数的参数传递 

10.c语言编程机制分别分为哪几个阶段?每个阶段做什么事情? 

11.scanf("%s",&name) 和gets(name)的区别

 二、运算符

1.运算符分类?写出优先级

2.赋值运算符注意事项

3.%运算符两边的操作符有什么限制

4./运算符有什么注意事项 

5.关系运算符的结果是什么? 

6.逻辑运算符的结果是什么? 

7.位运算符有哪些?运算规则是什么? 

8.操作 

9.请描述++操作的运算规则 

10.三目运算符实现一个闰年的判断 

三、控制语句 

1.选择语句有哪些?有什么区别?

2.循环语句有哪些?各自使用的场景 

3.break和continue区别 

四、函数 

1.函数解决什么问题?

2.函数的定一个是是什么?定义的时候有什么注意事项? 

3.函数的声明格式是什么?为什么需要函数声明?

4.函数形参参数格式是什么?形参类型有哪些?构造类型作为形参是接收什么的? 

5.返回值尅新有哪些?如果返回值为地址是用什么类型?构造函数作为形参接收的是什么? 

6.函数调用格式是什么?调用有哪一些注意事项? (形参、实参)

7.函数调用过程发生了什么? 

8.请描述值传递和地址传递的区别 

9.请描述递归函数,并说出优缺点

10.局部变量和全局变量的不同 

11.请说出变量存储的关键字,以及各个变量存储在内存的哪个位置?有什么特点?(auto、static、extern、register、volatile) 

 12.关键字static修饰函数内的变量和函数分别是什么作用?

五、数组

1.数组为了处理什么问题?

2.数组的定义格式是什么?数组中可以放什么数据类型的数据? 

3.如何分析一个数组?

4.数组元素的访问方式是什么?如何给数组中的元素进行赋值? 

5.如何给数组的每一个元素进行赋值?初始化的时候要注意哪些? 

6.数组当中元素在内存中是如何排序的? 

7.如何通过数组名访问到每一个元素的地址和元素? 

8.常见的字符串处理函数有哪些? 

9.怎么定义一个二维数组 

10.如何访问二维数组的数据以及他们的地址? 

11.二维数组如何进行赋值?要有什么注意的? 

12.如何通过二维数组名的形式访问到每个数据的地址以及存储数据? 

13.如何存储多个字符串如何定义数据类型?怎么访问? 

14.如何获取一个数组的长度 

六、指针 

1.定义?什么是地址?什么是空间?

2.定义指针的格式是什么? 

3.如何分析一个指针?指针指向的对象可以是什么数据类型? 

4.如何通过指针名对指针指向空间进行读写操作? 

5.如何改变指针的指向 

6. 指针变量空间大小是多少?指向不同数据类型的指针数据大小是一样的吗?为什么?

7. 指针偏移如何计算?和什么有关?

8. 定义一个指向有 10 个 int 型数据的数组首元素的指针

9. 定义一个指向一个指向用户姓名的指针

10. 指针直接指向一个常量字符串和指针指向一个盛放字符串的数组有什么区别?

11. 什么是数组指针?如何定义?

12. 通过数组指针访问数组中的元素?

13. 什么是指针数组?如何定义?

14. 如何通过指针数组取访问数据?

15. 指针在函数中有哪些应用?

16. 什么是指针函数?哪些类型可以作为指针函数的返回值类型?

17. 什么是函数指针?如何定义?如何调用?应用场景是?

18. 如何定义一个二级指针?二级指针和一级指针的区别是什么?

19. 如何通过一个二级指针,获取到变量空间的数据值?

20. NULL 和 void *的区别是什么?

 七、结构体

1.结构体用来解决什么问题?

2. 结构体定义的格式?结构体类型的成员可以是什么类型?

3. 使用结构体类型定义变量的格式?

4. 结构体变量访问成员的方式?

5. 结构体变量或者结构体类型所占空间大小如何计算?

6. 什么是字节对齐,有什么规则?

7. 如何将一个结构体变量里面的内容赋值到另外一个结构体变量中?

8. 结构体指针访问指向的对象的成员如何访问?

9. 如何定义一个结构体数组?如何访问结构体数组中的元素?

八、共用体 

1.定义

2. 共用体变量如何声明?如何确定共用体变量或者共用体类型所占的字节数?

3. 共用体的应用场景有哪些?

4. 什么是大小端?为什么有大小端之分?

九、枚举

1.枚举用来解决什么问题?有什么好处?

2. 枚举的标识符是一个整型数据吗?有什么样的取值规则?

3. 如何定义一个枚举变量,如何给枚举变量赋值?

十、动态内存分配 

1.动态分配的空间在哪个区?有什么特点?

2. 动态分配空间的函数有哪些?有什么区别?

3.如何释放动态内存空间?

4. free 函数使用有什么注意事项?

十一、宏定义 

1.宏定义是来解决什么问题?在哪一个阶段进行处理?处理的规则是?

 2.使用宏定义定义一个常量的值和使用const定义一个常量有什么区别?(#define N 100和const int n = 100)

十二、条件编译

1.什么是条件编译?

2. 如何防止一个头文件的重复引用?

3. 条件结构和条件编译的不同?


一、数据类型

1.基本的数据类型

C语言基础的数据类型:整型、实型、字符型、无值型;

其中,char类型占用1个字节;short短整型占用2个字节;int整型和long长整型占用4个字节;空类型是一个未知的类型,不能表示一个真实的变量;指针类型是一个特殊的变量,他里面存储的数值被解释为内存的地址。

2.变量的定义格式是什么?给变量复制有几种方式?

变量定义的格式:数据类型和变量名;

变量复制:赋值号=   或者直接输入

3.定义一个变量 ,向变量写入10

int a=10;或者scanf(%d,&a)

4.使用const定义的变量有什么特点? 

const定义的变量是一个不可以被修改的常量值,因为值不可以被修改,所以在定义的时候要把值定义好;

使用const定义变量的是格式:const 数据类型 变量名 = 值或者可以是数据类型const 变量名=值;比如就是const int n=10;或者 int const a=10;都是一样的,因为const和数据类型控制的是不同的方向,const控制的是值,数据类型控制的是开辟的空间大小,因此两个可以相互交换。

5. 数据在内存中是怎么存储的?数据溢出会发生什么事情?

数据在内存中的统一采用的是补码的的形式进行数据存储,数据溢出多的话,就会发生环形转换将这个数据转成可以表示的数。如果数据增长到最大值,那么这个数据可以从最小值方向开始依次递增;如果数据减到最小值,那么这个数据从最大值的方向递减。

 

6.什么是源码、补码、反码? 

数据在存储当中统一都是采用补码的形式进行的;

整型:源码==反码==补码;

负数的补码获取:原码:即将数据的数组转换成二进制,然后根据数据的累心确定数据占几位,再根据政府数据位设为0或者1;

反码:保持符号为不便,将其他位取反;

补码:反码+1;

7.char a=200;在内存中怎么存储的? 

  1. char是有符号类型,取值范围-128-127;存储200的时候已经越界了,因此就会发生环化(环形转换),将200变成在-128-127之间可以表达的值,那就是200-256,=-56.-56可以在这个范围内进行表示,所以存的的-56;
  2. 也可以将其直接表示为200的原码1100 1000,因为a是一个有符号的数,因此最高位为符号位不是一个数据位,但是a里面存储的还是这个1100 1000的码,这个数的一个负数的补码
  3. 反码:1100  1000;
  4. 原码:1011 11000 -(32+16+8)=-56

8.sizeof的作用是什么?该怎么使用? 

sizeof用于计算数据类型所占字节数的多少,sizeof(数据类型或者变量名)

9.说一说printf函数的参数传递 

C语言当中调用的时候,参数需要用到堆栈传递,但是参数压栈顺序是从右到左边的。

比如:

int m =5;

int n=10;

printf("%d%d",m,m+n);

 

10.c语言编程机制分别分为哪几个阶段?每个阶段做什么事情? 

预处理:在编译之前完成工作,找文件并把文件的内容复制过来,去掉注释,宏替换,条件编译->文本替换->并不会进行语法错误检查;

编译:检查语法是否有错误,声称汇编文件;

汇编:将汇编语言变成二进制文件,生成.s文件;

链接:将机器语言转换成执行文件,.exe文件

11.scanf("%s",&name) 和gets(name)的区别

scanf使用的是%s读取字符串会将缓冲区的换行忽略掉;

gets会读取缓冲区的换行符,遇到换行符结束


 二、运算符

1.运算符分类?写出优先级

6类:复制-复合、算数运算符、关系运算符、逻辑运算符、位运算、其他(++、-- 三目运算符、逗号运算符);

运算符优先级规则:

单目>双目>三目>赋值和复合>逗号

双目:算数运算符>左移、右移>关系运算符>按位与、或、非>逻辑运算符

2.赋值运算符注意事项

赋值运算符的左侧一定是一个空间而不是一个常量;

比如: int a[5]; a = {1,2,3,4,5}; 上述操作是错误的,因为数组每个值数组首元素的地址,是一个常量,
不能放在赋值符号的左侧,因此数组的整体赋值是在初始化的时候,除此之外不能整体赋值。

 赋值运算符两边数据类型要一致,如果不一致会以左侧的数据类型为依据,尝试将右侧的数据转换成左侧的类型,如果转换不了就会报错

3.%运算符两边的操作符有什么限制

%两边的操作数,必须都是整数类型

4./运算符有什么注意事项 

/两边数据类型收拾整型数据类型页数整型数据,如果有一个或者两个都是实行数据则结果为实型数据    5/3==1     5.0/3=1.666667

5.关系运算符的结果是什么? 

0     1

6.逻辑运算符的结果是什么? 

0   1

7.位运算符有哪些?运算规则是什么? 

将数据便表示成二进制补码的形式进行运算

对应位:

&:全1为1,有0则0;

|:有1则1,全0为0;

~:1变0,0变1(包括符号位也要变化);

^:相同为0;不同为1;
<<;整体左移:低位补0,高位溢出舍弃;
>>:整体右移,低位溢出舍弃,高位补 符号位上的数字

8.操作 

如何将一个 32 位的低位的第 3 位置 0 ?将第 4 位置 1 ?判断第 5 位是 0 还是 1 ?将第 10 位和第 11 位同 时置 1 ?将第 18 位和 19 位同时置 01?Unsigned int a = 0x34567801;
  1. a&=~(1<<3);
  2. a|=~(1<<4);
  3. a&(1<<5);
  4. a|=(3<<10);
  5. a&=~(3<<18);a|=(1<<18)

9.请描述++操作的运算规则 

++ 单独使用,在前在后没有区别,比如: a++; ++a;
如果参与表达式和其他运算符一起使用时,如果 ++ 在前则先加再用,如果 ++ 在后则先用后加

10.三目运算符实现一个闰年的判断 

int res=(year%4==0&&year%100!=0)||(year%400==0)?1:0;


三、控制语句 

1.选择语句有哪些?有什么区别?

if-else和Switch-case:

if else适用于判断某一个条件是在某个范围内,使用范围比较大;

swtich-case适用于可以罗列出可能值的判断,另外case里面的语句不能有变量的声明,不然会报错;

2.循环语句有哪些?各自使用的场景 

for:适用于知道循环次数;

while:适用于知道结束条件的循环;

do-while:适用于无论怎么样都要执行一次的循环

3.break和continue区别 

break跳出离他最近的那一层循环,循环结束;

continue结束背刺循环,跳到下一个循环;


四、函数 

1.函数解决什么问题?

解决了代码复用的问题,增强代码的可维护性

2.函数的定一个是是什么?定义的时候有什么注意事项? 

函数的返回值类型  函数名(形参列表)

{

    //体积之心功能更的程序

  return 返回值;

}

3.函数的声明格式是什么?为什么需要函数声明?

函数返回类型 函数名(形参参数);

函数声明就是告诉编译器函数的返回值类型以及形参类型和个数,方便其进行语法检查:一般函数的声明是放在头部,函数的实现放在文件尾部或者其他文件中间都可以;

4.函数形参参数格式是什么?形参类型有哪些?构造类型作为形参是接收什么的? 

形参类型:形参名1,形参类型  形参2......

形参类型可以是C语言当中的任意数据类型,构造数据类型作为形参传递的是构造函数的手直接的地址,像数组,字符串、动态分配的内存等都是一些列数据的集合,一一赋值传递参数比较耗费时间和空间,编译器在处理值传递只传递他们的指针,在函数内部通过指针来影响这些数据的集合。

5.返回值尅新有哪些?如果返回值为地址是用什么类型?构造函数作为形参接收的是什么? 

c语言的数据类型都可以作为返回值类型;

返回的是一个地址那就用指针;

返回的地址不能是函数内部局部变量或形参的地址,因为他们的作用域作为当前函数,函数运行结束后没有办法办证一定可以拿到上次运行后的存储类型。

6.函数调用格式是什么?调用有哪一些注意事项? (形参、实参)

函数名(实参列表)

注意事项:

1.形参变量只有在韩式被调用的使用才可以分配内存,调用结束,释放内存,所以形参变量只能在内部有效,不能在函数外部使用;

2.实参可以是常量、变量、变大时、函数等等,不管是什么类型的数据,在进行函数调用的时候,他们都必须是确定的值,以便于把这些值传递给形参,所以应该提前复制、输入的方法是实参获得确定值。

3.实参和形参在数量上、类型上、顺序上都需要保存一直,不然就会发生“类型不匹配”的错误。当然,如果可以进行自动类型转换,或者进行强制类型转换,那么就可以实参类型也可以不同于形参类型;

4.函数调用中发生的数据类型是单向的,只能将实参的数传递给形参,而不能吧形参的值返现的传给实参;

5.形参和实参可以同名,但是它们之间是相互独立的,互不影响,因为实参在函数外部有效,而形参是在函数的内部有效

7.函数调用过程发生了什么? 

点用函数的时候,执行流程从调用使用该函数的代码转至呗调用函数之前,会首次完成参数的传递,即将实参的值传递给对应的形式参数,然后执行呗调用函数的代码,执行完毕之后再将返回值返回给调用处,并执行调用语句后面的代码。

8.请描述值传递和地址传递的区别 

值传递是单线传递,就是主调函数调用时给形参分配存储单元,把实参的值传递给形参,在调用结束后,形参的存储单元被释放,而形参值的任何变化都不会影响到实参的值,实参的存储单元任然保留并维持数值 不变;

地址传递:是形参并不存在存储空间,编译西永部位形参数值分配内存空间。数组名或者指针就是一组连续空间的首地值。因为在数组名或者指针函数参数是进行的传送只是地值传送,形参在去的该首地址之后,一实参共同拥有一段内存空间,形参的变化也就是实参的变化。

9.请描述递归函数,并说出优缺点

递归函数:直接或间接调用使用函数本身的函数;

注意的是:递归函数必须要有一个可以种植递归调用的条件,否则会一直递归下去;

优点:写法简单;

缺点:占内存,变量需要移植保存在作用域;

10.局部变量和全局变量的不同 

码文件中使用,有些变量只能在当前的文件中使用,有些变量只能在函数内部使用,有些变量只能在 for
循环内部使用。
变量的作用域由变量的定义位置决定,在不同位置定义的变量,它的作用域是不一样的。
根据作用域的不同, C 语言的变量分为全局变量、局部变量、块级变量。
①全局变量:
在所有函数的外部定义变量;作用域:整个程序,所有的代码文件,程序结束后被销毁 ; 全局变量不赋
初值默认为 0
②局部变量:
在函数内部定义的变量就是局部变量,形参也是局部变量;作用域:定义的函数内部,函数运行后被销
毁;局部变量不赋初值为垃圾值。
③块级变量:
在代码块中定义的变量,比如:函数体、选择结构、循环结构;作用域:所在代码块,出了代码块访问
不到;不赋初值为垃圾值

11.请说出变量存储的关键字,以及各个变量存储在内存的哪个位置?有什么特点?(auto、static、extern、register、volatile) 

在执行一个 C 语言程序时,操作系统把硬盘中的数据下载到内存中,并将内存分为五个区域:代码区、
常量区、全局数据区、堆区、栈区,由操作系统找到 main 函数入口开始执行程序。

 

  1. Auto:根据定义的位置决定存在哪个区域,全局数据放入全局数据区,局部变量存在栈区;
  2. Static:存储在全局数据区
  3. Extern:用来声明一个外部(其他文件中)的变量或函数
  4. Register:变量存在寄存器中
  5. Volatile:变量随时都有可能改变,编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量
  6. 地址中读取数据。如果没有 volatile 关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的
  7. 值,如果这个变量由别的程序更新了的话,将出现不一致的现象。

 12.关键字static修饰函数内的变量和函数分别是什么作用?

  1. static 声明的变量称为静态变量,不管它是全局的还是局部的,都存储在静态数据区(全局变量本来就 存储在静态数据区,即使不加 static)。
  2. 静态数据区的数据在程序启动时就会初始化,直到程序运行结束;对于代码块中的静态局部变量,即使 代码块执行结束,也不会销毁。
  3. 注意:静态数据区的变量只能初始化(定义)一次,以后只能改变它的值,不能再被初始化,即使有这 样的语句,也无效。
  4. static 修饰局部变量,该变量在函数结束后空间不会被销毁,因为存储在静态数据区。
  5. static 修饰全局变量,则该变量只能在本文件中使用,不能被外部文件引入。
  6. static 修饰函数,则该函数只能在本文件中使用,不能被外部文件引入。

五、数组

1.数组为了处理什么问题?

大量数据类型数据的操作处理

2.数组的定义格式是什么?数组中可以放什么数据类型的数据? 

元素数据类型 数组名【个数】;

数组中可以放C语言的任意一种数据类型;

3.如何分析一个数组?

数组分析:
数组名
元素的个数
每个元素的下标
元素的数据类型:除了 数组名 [ 元素的个数 ] 剩下的就是元素的数据类型。
数组的类型:除了 数组名 剩下的就是它的数据类型。

4.数组元素的访问方式是什么?如何给数组中的元素进行赋值? 

 数组元素的访问即获取到元素所在的空间

1 、通过下标,数组名 [ 下标 ];
2 、通过地址查找空间 *( 数组名 + 偏移元素个数 ), 原理:数组名为数组首元素的地址,数组中的数据都 是同种类型,因此偏移的时候是等量字节的偏移。
赋值:空间 =

5.如何给数组的每一个元素进行赋值?初始化的时候要注意哪些? 

 

初始化进行整体赋值;
先定义然后根据下表拿到每个空间进行单独赋值
循环:数组的下标是连续的,因此可以使用循环获取每一个空间,然后赋值
初始化的时候:
元素个数可以省略, {} 元素个数就是初始化数据个数
数据个数可以少于元素个数,没有初始化的元素默认为 0
数据个数不能大于数组定义中元素个数

6.数组当中元素在内存中是如何排序的? 

元素在内存中的空间连续分配。
数组名就是数组首元素地址

7.如何通过数组名访问到每一个元素的地址和元素? 

地址:数组名 + 偏移量
数据:获取空间, *( 数组名 + 偏移量 )

8.常见的字符串处理函数有哪些? 

①字符串有效长度计算函数
n = strlen( 数组名 );
②字符串复制函数
strcpy(str1,str2);
将字符串 2 复制给字符串 1
③字符串拼接函数
strcat(str1,str2);
将字符串 2 拼接在字符串 1 后面
④字符串比较函数
n = strcmp(str1,str2);
返回值是 0 就相等

9.怎么定义一个二维数组 

数据类型 数组名 [ 元素个数 ][ 每个元素中的数据个数 ];

10.如何访问二维数组的数据以及他们的地址? 

获取数据空间:数组名 [ 元素下标 ][ 元素中的数据下标 ]
地址: & 数组名 [ 元素下标 ][ 元素中的数据下标 ]

11.二维数组如何进行赋值?要有什么注意的? 

初始化整体赋值 ;
通过两层下标拿到数据所在空间单个赋值 ;
两层循环赋值;
注意事项:
在数组初始化语句,元素数目可以省略
但是每个元素的数据个数不能省略; // 元素中的数据个数不能省略

12.如何通过二维数组名的形式访问到每个数据的地址以及存储数据? 

 

Int a[2][3] = {{3,4,5},{7,9,10}}; // 获取 9
地址: *( 数组名 + 元素的偏移 )+ 元素中数据的偏移
*
a+1 +1
数据: *
*( 数组名 + 元素的偏移 )+ 元素中数据的偏移) *
*
a+1 +1

13.如何存储多个字符串如何定义数据类型?怎么访问? 

 char str[2][30]={"ssss","ssssqqqq};Printf(“%s %s”,str[0],str[1]);

14.如何获取一个数组的长度 

Sizeof( 数组名 )/sizeof( 元素的类型 )

六、指针 

1.定义?什么是地址?什么是空间?

指针:指针变量,它指向内存中的一块地址 -- 存储一个地址编号 - 指向对象的类型 - 指向的空间的大小
地址:内存中会按照字节进行编号,字节在内存中编号
空间:从这个地址编号开始,存放对象数据类型个字节大小的空间。

2.定义指针的格式是什么? 

 指向对象的数据类型 *指针变量名;

3.如何分析一个指针?指针指向的对象可以是什么数据类型? 

指针分析的三要素:
①指针变量名
②变量名的类型
除了变量名以外的内容就是变量名的类型
③指向对象的类型
除了 * 变量名以外的内容就是指向对象类型

4.如何通过指针名对指针指向空间进行读写操作? 

* 指针名 代表的是指针指向的空间
读操作: * 指针名
写操作: * 指针名 =

5.如何改变指针的指向 

给指针赋值
Int a = 30,b = 50;
Int *p = &a;
p = &b;

6. 指针变量空间大小是多少?指向不同数据类型的指针数据大小是一样的吗?为什么?

4 个字节
指针变量所占的字节数和指针指向对象的数据类型无关。
因为指针存储的是变量的地址,是一个 8 位十六进制数,从 00000000~ffffffff,
ffff ffff=16^8=2^4^8=2^32b=2^22kb=2^12mb=2^2gb=4gb
00000000~ffffffff 可以表达 4gb 内存大小的地址编号,对于运行内存来说足够了

7. 指针偏移如何计算?和什么有关?

指针的偏移跟 指向对象的数据类型 有关。
指针偏移 是以 指向对象的数据类型所占字节数为 单位进行偏移的
例如:
int *p
指针跳动一步,指针变量里存储的 地址编号就偏移 4
//p 的值 +4
char *p
指针跳动一步,指针变量里存储的 地址编号就偏移 1
//p 的值 +1
short *p
指针跳动一步,指针变量里存储的 地址编号就偏移 2
//p 的值 +2
指针可以和整数进行加法操作
指针可以和整数进行减法操作
指针可以和指针进行减法操作 - 得到的结果为:相差的单位数

8. 定义一个指向有 10 int 型数据的数组首元素的指针

int a[10];

int *p=a;

9. 定义一个指向一个指向用户姓名的指针

Char username[] = “liming”
Char *str = username

10. 指针直接指向一个常量字符串和指针指向一个盛放字符串的数组有什么区别?

指针指向一个常量字符串是不允许通过指针对字符串进行部分修改的,因为它是一个常量
指针指向一个盛放字符串的数组,那么可以对数组中的字符进行修改操作

11. 什么是数组指针?如何定义?

一个指针,指向的对象是一个一维数组(注意他不是数组找个某个元素,而是数组这个整体)
数据的类型(
* 指针名) [ 元素的数据个数 ]
Int (*p)[3] = {{1,2,3},{4,5,6}}

12. 通过数组指针访问数组中的元素?

*(* (指针名 + 二维数组元素的偏移量) + 某个元素的数据的偏移量 )
Int (*p)[3] = {{1,2,3},{4,5,6}}
4:*(*(p+1)+0)
5:*(*(p+1)+1)
p 指针指向的对象是: int [3], 因此一次偏移偏移一个 int [3]

13. 什么是指针数组?如何定义?

如果一个数组中的所有元素保存的都是指针,那么我们就称它为指针数组。
数据类型
* 数组名 [ 元素个数 ]
或者 数据类型
*( 数组名 [ 元素个数 ]);
int a = 20,b = 30;
Int *p[3] = {&a,&b};

14. 如何通过指针数组取访问数据?

Int *p[3] = {&a,&b};
a:*(p[0]) 或者 *(*(p+0))
b:*(p[1]) 或者 *(*(p+1))
先考虑数组然后再考虑指针

15. 指针在函数中有哪些应用?

指针作为函数形参 - 集合类型传参
指针作为函数返回值 - 指针函数 ( 一个函数返回值是一个指针 )
个指针指向一个函数,调用 - 函数指针

16. 什么是指针函数?哪些类型可以作为指针函数的返回值类型?

 

C 语言允许函数的返回值是一个指针(地址),我们将这样的函数称为指针函数。
定义:
数据类型 * 函数名 ( 函数的形参 )
{
函数体
return 指针 ;
}
C 语言里面的数据类型都可以作为指针函数的返回值类型

17. 什么是函数指针?如何定义?如何调用?应用场景是?

一个指针指向一个函数,通过指针进行函数的调用。
定义:
函数返回值类型 (* 指针名 )( 形参列表 )
void (*mm)(void);
使用:
①定义一个函数指针
确定指向对象(函数) 的 返回值类型
参数类型
②将要指向的函数的地址(函数名)赋值给指针变量
③调用: (* 指针变量名 ) (实参) ;
使用场景:函数作为形参传递,比如:回调函数等

18. 如何定义一个二级指针?二级指针和一级指针的区别是什么?

如果一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针。
C 语言不限制指针的级数,每增加一级指针,在定义指针变量时就得增加一个星号 *
指向的对象的数据类型 ( 指针类型 ) * 二级指针名 ;
Int a = 20;
Int *p = &a;
Int **q = &p; // q 为二级指针,它的指向对象是 int *
一级指针里面保存的数据的地址,二级指针里面保存的是一级指针的地址

19. 如何通过一个二级指针,获取到变量空间的数据值?

** 指针名
**q 为二级指针指向的一级指针指向的空间,通过它可以对该空间进行读写操作。

20. NULL void *的区别是什么?

NULL 零值、等于零 的意思,在 C 语言中表示空指针。
NULL 是在 stdio.h 中定义的一个宏,它的具体内容为:
#define NULL ((void *)0)
NULL 指向了地址为 0 的内存,在进程的虚拟地址空间中,最低地址处有一段内存区域被称为保留区,
这个区域不存储有效数据,也不能被用户程序访问,将 NULL 指向这块区域很容易检测到违规指针。
void * 表示一个有效指针,它确实指向实实在在的数据,只是数据的类型尚未确定,在后续使用过程中
一般要进行强制类型转换。
比如: C 语言动态内存分配函数 malloc() 的返回值就是 void * 类型,在使用时要进行强制类型转换。

 七、结构体

1.结构体用来解决什么问题?

将多个不同类型的数据放在一起,形成一个整体,类似面向对象中的类

2. 结构体定义的格式?结构体类型的成员可以是什么类型?

struct
结构体名
{
成员数据类型 1 成员名 1;
成员数据类型 2 成员名 2;
成员数据类型 3 成员名 3;
成员数据类型 4 成员名 4;
};
结构体成员可以是 c 语言的任意一种数据类型。

3. 使用结构体类型定义变量的格式?

struct
结构体名 变量名;
结构体别名 变量名;

4. 结构体变量访问成员的方式?

结构体变量 . 成员名

5. 结构体变量或者结构体类型所占空间大小如何计算?

Sizeof( 结构体类型 ) 或者 sizeof( 结构体变量 )

6. 什么是字节对齐,有什么规则?

结构体中的成员在内存中是按字节对齐的方式存储的!
规则为:
1 、找到结构中占用空间最大的数据类型 -max 个字节
2 、以 max 个字节为单位分配空间
3 、每个成员按照顺序分配内存,内存不够再以 max 字节为单位进行分配
4 、每个成员距离结构体的首地址之间的距离必须是成员本身所占字节数的整数倍
5、结构体类型所占空间为上述分配空间之和

7. 如何将一个结构体变量里面的内容赋值到另外一个结构体变量中?

结构体变量可以直接复制,复制相当于拷贝一份数据放入变量名 2 的相应的空间中。
Struct 结构体名 变量名 1 = {........};
Struct 结构体名 变量名 2 = 变量名 1

8. 结构体指针访问指向的对象的成员如何访问?

结构体指针名->成员名

9. 如何定义一个结构体数组?如何访问结构体数组中的元素?

Struct 结构体名 数组名 [ 元素个数 ]
通过数组下标访问结构体数组中的结构体

八、共用体 

1.定义

多个成员共用同一块内存

2. 共用体变量如何声明?如何确定共用体变量或者共用体类型所占的字节数?

union 共用体名
{
成员类型 成员名;
......
}
共用体类型: union 共用体名
共用体所占字节数取成员中占用字节数最大的值,可以使用 sizeof(union 共用体名 )

3. 共用体的应用场景有哪些?

大小端判断,方便通信传输中的 float 类型数据传递

4. 什么是大小端?为什么有大小端之分?

大端模式( Big-endian ),是指数据的高字节,保存在内存的低地址中,而数据的低字节,保存在内存 的高地址中;
小端模式( Little-endian ),是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的 低地址中.
在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为 8bit 。但是在C 语言中除了 8bit 的 char 之外,还有 16bit 的 short 型,32bit 的 long 型(要看具体的编译器),另外对于位数大于 8 位的处理器,例如 16 位或者 32 位的处理器,由于寄存器宽度大于一个字节,那么必 然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。
我们常用的 X86 结构是小端模式,而 KEIL C51 则为大端模式,很多的 ARM DSP 都为小端模式。

 


九、枚举

1.枚举用来解决什么问题?有什么好处?

程序用枚举方法列举一组 标识符 作为枚举类型的 值 的 集合,增强代码的可阅读型。

2. 枚举的标识符是一个整型数据吗?有什么样的取值规则?

标识符是一个整型数据,可以直接使用,取值如果没有默认值采用从 0 开始一次增 1 计数,如果有默认
值使用默认值,其后的标识符的值看离他最近的标识符的值上增 1.

3. 如何定义一个枚举变量,如何给枚举变量赋值?

枚举类型 变量名 ;
枚举类型变量赋值等同于整型变量赋值操作。
Enum Color{RED,GREEN,BLUE};
Enum Color light;
Scanf(“%d”,&light); 或者 light = 1;

十、动态内存分配 

1.动态分配的空间在哪个区?有什么特点?

堆区,需要程序员自己申请,自己释放,如果不释放,程序结束后由操作系统释放。

2. 动态分配空间的函数有哪些?有什么区别?

Malloc calloc
函数调用形式: malloc( 总的字节数 ) malloc 不会初始化申请的空间
Calloc( 几块,每块几个字节 ) calloc 或初始化申请的空间

3.如何释放动态内存空间?

Free(p)

4. free 函数使用有什么注意事项?

free 必须释放的是堆区空间,不能释放栈区空间,比如局部变量,否则会造成程序崩溃


十一、宏定义 

1.宏定义是来解决什么问题?在哪一个阶段进行处理?处理的规则是?

表达式(常量、变量、运算符和操作数)的复用,在于处理阶段完成替换,只会进行替换而不会将后面的表达式看成一个整体。
比如 #define M(x) x*x
Int a = 2,b=3;
M(a+b) == a+b*a+b = 2 + 2 *3 + 3 = 11

 2.使用宏定义定义一个常量的值和使用const定义一个常量有什么区别?(#define N 100和const int n = 100

①处理阶段:宏定义在预处理阶段完成替换, const 常量在运行阶段分配空间
②占空间:宏定义不占空间, const 常量要占空间
3 、带参宏和函数的区别?
①处理阶段:带参宏在预处理阶段完成替换,函数在运行阶段执行
②占空间:宏定义不占空间,函数要占空间
③复杂逻辑:宏定义不能执行复杂逻辑,比如 if 嵌套,循环等,函数可以

十二、条件编译

1.什么是条件编译?

根据不同情况编译不同代码、产生不同目标文件的机制,称为条件编译。条件编译是预处理程 序的功能,不是编译器的功能。

2. 如何防止一个头文件的重复引用?

#ifndef __M__
#define __M__
#include<xx.h>
#endif

3. 条件结构和条件编译的不同?

①、选择结构是全部编译,条件编译时部分编译
②、选择结构是运行时处理,条件编译是预处理时处理。

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丘比特惩罚陆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值