一、数据类型
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;在内存中怎么存储的?
- char是有符号类型,取值范围-128-127;存储200的时候已经越界了,因此就会发生环化(环形转换),将200变成在-128-127之间可以表达的值,那就是200-256,=-56.-56可以在这个范围内进行表示,所以存的的-56;
也可以将其直接表示为200的原码1100 1000,因为a是一个有符号的数,因此最高位为符号位不是一个数据位,但是a里面存储的还是这个1100 1000的码,这个数的一个负数的补码
反码:1100 1000;
原码: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;
- a&=~(1<<3);
- a|=~(1<<4);
- a&(1<<5);
- a|=(3<<10);
- 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 函数入口开始执行程序。
- Auto:根据定义的位置决定存在哪个区域,全局数据放入全局数据区,局部变量存在栈区;
- Static:存储在全局数据区
- Extern:用来声明一个外部(其他文件中)的变量或函数
- Register:变量存在寄存器中
- Volatile:变量随时都有可能改变,编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量
- 地址中读取数据。如果没有 volatile 关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的
- 值,如果这个变量由别的程序更新了的话,将出现不一致的现象。
12.关键字static修饰函数内的变量和函数分别是什么作用?
- static 声明的变量称为静态变量,不管它是全局的还是局部的,都存储在静态数据区(全局变量本来就 存储在静态数据区,即使不加 static)。
静态数据区的数据在程序启动时就会初始化,直到程序运行结束;对于代码块中的静态局部变量,即使 代码块执行结束,也不会销毁。
注意:静态数据区的变量只能初始化(定义)一次,以后只能改变它的值,不能再被初始化,即使有这 样的语句,也无效。
static 修饰局部变量,该变量在函数结束后空间不会被销毁,因为存储在静态数据区。
static 修饰全局变量,则该变量只能在本文件中使用,不能被外部文件引入。
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( 元素的类型 )