【C语言】c语言基础知识梳理(超全)

您所在的位置:网站首页 地理基础知识总结大全视频讲解 【C语言】c语言基础知识梳理(超全)

【C语言】c语言基础知识梳理(超全)

2024-07-17 22:28:52| 来源: 网络整理| 查看: 265

C语言基础知识梳理 零、概述一、变量和基本类型(一)基本类型1、有符号常见类型大小及其范围2、浮点数范围来由及其有效数字3、字面值常量(1)十进制字面值(2)浮点数字面值(3)指定字面值类型 4、字符和字符串常量5、总结 (二)变量1、定义变量2、常用特殊前缀3、数组与初始化变量4、变量作用域(1)局部变量与全局变量的差别 (三)字符串(四) 自定类型——结构体 二、表达式三、语句(一)条件语句1、if语句2、switch语句 (二)迭代语句1、while语句2、do while语句3、for语句 (三)跳转语句 四、函数(一)函数一般格式(二)函数声明(三)结构体中的函数 五、指针(一)定义(二)结构体与指针(三)数组与指针 六、文件读取(一)文本文件(二)二进制文件 七、编译预处理指令与.h文件(一)编译预处理指令1、# include < stdio.h >2、#define 名称 操作(宏定义)3、(补充)inline内联函数 (二).h文件(三)一些常用宏 八、常用函数(一)常用函数(二)scanf和printf    

零、概述

写此篇博客的目的主要是为了梳理一下c语言基础知识,因为不会像c语言教程那样有很多例子,或者按照初学c语言的顺序,所以不推荐刚学习c语言的人阅读。(期末复习可以看看)

本篇文章有什么:

对c语言系统的梳理对一些使用的细节进行梳理解答对使用c语言时产生的一些疑惑本篇内容基于“C语言程序设计-浙江大学-翁恺”、“C++ Primer”部分内容以及个人理解进行梳理,不充分之处欢迎指出       一、变量和基本类型 (一)基本类型 1、有符号常见类型大小及其范围

1byte(字节)=8bit(位);每个bit就是一个0或者1,byte是c语言里面数据的最小单位

常用2的次方: 27=128 28=256 215=32,768 216=65,536 231=2,147,483,648‬ 232=4,294,967,296 263=9,223,372,036,854,775,808‬ 264=18,446,744,073,709,551,616

类型含义32位编译器中大小(一般)64位编译器中大小(一般)最小值(32位)最大值(32位)bool(stdbool.h)布尔类型1byte1bytefalsetruechar单个字符1byte1byte-2727-1short短整形2byte2byte-215215-1int整形4byte4byte-231231-1long长整形4byte8byte-231231-1long long长整形8byte8byte-263263-1float单精度浮点数4byte4byte-21272128double双精度浮点数8byte8byte-2102321024long double扩展精度浮点数12byte16byte-216383216384char*字符常量或字符串常量4byte8byte无意义无意义

2、浮点数范围来由及其有效数字

这里单独讨论一下浮点数的取值范围,浮点数都遵循IEEE754标准,所以: 4*8=32位的float的第1位是符号位,第2~9位有8位是指数位,第10~32位有23位是尾数位   那么可以很容易看到float的范围是[-1*2127≈1.7*1038, 1*2128≈3.4*1038]

因为转换成IEEE754都要进行标准化,也就是将原来的整数点整数的形式转化成二进制点二进制的形式,然后将点的位置移动到左边第一个1(2)之后,产生指数位。规定点之后的数填在尾数位上,所以31位前暗含了1(2),所以上面的范围会先乘个1。 32位的指数位 = 移位数(左移一位+1,右移一位-1)+ 127得出。所以负数只有127(127-127=0),而正数有128(127+128=255)

  8*8=64位的double的第1位是符号位,第2~12位有11位是指数位,第13~64位有52位是尾数位 那么可以很容易看到float的范围是[-1*21023≈8.988*10307, 1*21024≈1.797693*10308]   12*8=96或16*8=128位的long double的第1位是符号位,第2~16位有15位是指数位,在32位系统中第17~96位有80位是尾数位,在64位系统中第17~128位有112位是尾数位,那么范围是[-1*216383≈5.9*104931, 1*216384≈1.1897*104932](与尾数大小无关)。   其实float的范围就已经非常非常大了,那为什么还会有double甚至long double呢,这是因为浮点数能准确记录量级,但是无法准确记录太长的数字,数字的有效位数值取决于尾数位的长度,我们可以总结成下表:

类型有效位数计算有效位数float223+1=16,777,2168-1=7double252+1=9,007,199,254,740,992‬16-1=15long double280+1=2.4*10 24 / 2112+1=1.038*103425-1=24 / 35-1=34

3、字面值常量 (1)十进制字面值

对于一个20(10)=24(8)=14(16),在c语言中对应表达为20(10进制)、024(8进制)、0x14(16进制)。 默认情况下,十进制字面值的类型是int,如果int装不下就是long,再装不下就是long long。

(2)浮点数字面值

对于一个浮点数可以表示为314.159(10)也可以表示为3.14159e+2(科学记数法)。 默认情况下,浮点数字面值是一个double

(3)指定字面值类型 整形字面值后缀最小匹配类型例子u / Uunsigned20u / 20Ul / Llong20l / 20Lll / LLlong long20ll / 20LL浮点形字面值f / Ffloat20.0f / 20.0Fl / Llong double20.0l / 20.0L   4、字符和字符串常量

形如’a’、"HelloWorld"都可以看作是常量,特别说明当例如char* s1="HelloWorld";char* s2="HelloWorld";时,s1和s2所指的都是内存中代码段的常量,可读不可写且地址相同,类似于const char* s1;

字符是以单引号’括住的单个字符,只占一个char(一个byte) 字符串以双引号"括住一系列字符,最后隐含了’\0’,所以占n+1个char(n为字符串有意义的长度)

特殊的常量:无穷,每个编译器的表示都不一样,可以使用如下代码输出:

printf("%f\n", 1/0.0); // 无穷大。我的电脑上为:1.#INF00 printf("%f\n", -1/0.0); // 无穷小。我的电脑上为:1.#INF00 printf("%f\n", 0.0/0.0); // 空。我的电脑上为:-1.#IND00

5、总结

有符号的类型(除浮点数)的范围都是由[-2n-1, 2n-1-1](n为类型所占bit) 无符号的类型(除浮点数)的范围都是由[0, 2n-1](n为类型所占bit) 浮点数的范围与其指数位大小有关,为[-2{[2^(m-1)]-1}, 2[2^(m-1)]](m为指数位位数)    

(二)变量 1、定义变量

变量由一个类型声明符加一个或多个变量名组成的列表(c99及以后可以在函数内任意位置定义变量),例如:

int a; // a是int类型的变量 double b=1.0; //b是double类型的变量,赋1.0为初值 char c, d; // c, d是char类型的变量

2、常用特殊前缀 extern int a; // 声明一个int类型的变量a,一般用在.h文件中声明项目全局变量 const int b=1; // 定义一个不可变的变量b,使用const关键字都要赋初值 static int c=1; // 在函数中使用,只在第一次使用时初始化,相当于作用域在函数内的全局变量 typedef long long int; // 把long long当作int使用

3、数组与初始化变量 int a=1; // 给a初始化为1 // 以下为C99加入的特性 int b[10] = {1}; // 第一个元素初始化为1,其他9个元素初始化为0 int c[10] = {0}; // 全部初始化为0,常用初始化手段 int d[10] = {[1]=1, 2, [4]=4}; // 0 1 2 0 4 0 0 0 0 0

4、变量作用域

变量有两种类型:局部变量全局变量,变量作用域即变量可使用的范围。   对于局部变量可以简单理解为大括号{}内即为一个作用域,变量在哪个大括号内,作用域就在哪。   对于全局变量的作用域就是在当前的.c文件中,在.h文件声明后可以在整个项目内使用。   对于同名变量,小作用域的变量会在其作用域中覆盖大作用域的变量。  

(1)局部变量与全局变量的差别 差别因素局部变量全局变量初始值初始值取决于内存里的数(随机)一般为0,指针为null作用域仅限于大括号内.c文件甚至项目

(三)字符串

字符串在c语言中有两种形式char*和char[],这里简单分辨下两者之间的不同。 char* c1="HelloWorld!"中,c1指向代码段中的常量,只读不写,且常量相同,指向的地址也相同。 char c2[]="HelloWorld!"中,c2指向堆栈段中的数据,可读可写,相当于把代码端的数据拷贝了出来。  

(四) 自定类型——结构体

结构体可以看作是一种个基础类型复合的类型。

// 声明如下: struct DATE{ int year, month, day; }; // 几种定义方式如下: struct DATE date1; // 不赋初值 struct DATE date2={2020, 4, 5}; // 根据结构体中的顺序赋初值,这里是年月日 struct DATE date3 = {.year=2020, .day=5}; // 给单独变量赋初值 struct DATE *date4 = &date3; // 用指针取date3地址(指针后面会单独说) // 几种赋值方式如下: date3 = (struct DATE){.year=1999}; // 将数据强制转换成struct DATE类型赋值 date3 = date2; // 自动赋值 date3.year=2010; // 对变量中单一元素赋值 date4->year=2010; // 对指针所指变量中的单一元素赋值 // 常用声明 typedef struct DATE2{ int year, month, day; } D; D date5; // 这样就可以不用写struct DATE2这么一长串,取而代之用D来表示

扩展:union union作为关键字与struct类似,但是struct中每个成员都是单独的内存,而union只占最大成员变量的大小,通常用与二进制与十进制的转换。

union DATE{ int year; int month; int day; }; /* 一个union DATE只有一个int大小 */

扩展:enum枚举,枚举类似#define,但是有体系些(c语言的枚举不好用)

// 声明枚举, 默认下标RED:0, YELLOW:1, GREEN:2 enum COLOR1 {RED1, YELLOW1, GREEN1}; // 自定下标 enum COLOR2 {RED2=1, YELLOW2, GREEN2=5};

     

二、表达式

这里给出运算符优先级

优先级运算符名称或含义使用形式结合方向说明1[]数组下标数组名[整型表达式]左到右 ()圆括号(表达式)/函数名(形参表).成员选择(对象)对象.成员名->成员选择(指针)对象指针->成员2-负号运算符-算术类型表达式右到左单目运算符(type)强制类型转换(纯量数据类型)纯量表达式++自增运算符++纯量类型可修改左值表达式单目运算符--自减运算符--纯量类型可修改左值表达式单目运算符*取值运算符*指针类型表达式单目运算符&取地址运算符&表达式单目运算符!逻辑非运算符!纯量类型表达式单目运算符~按位取反运算符~整型表达式单目运算符sizeof长度运算符sizeof 表达式 / sizeof(类型)3/ 除 表达式/表达式 左到右双目运算符*乘表达式*表达式双目运算符%余数(取模)整型表达式%整型表达式双目运算符4+加表达式+表达式左到右双目运算符-减表达式-表达式双目运算符5整型表达式双目运算符6>大于表达式>表达式左到右双目运算符>=大于等于表达式>=表达式双目运算符 (移位运算) > 判断运算符(比较>相等) > (位运算) > 逻辑运算符(&&>||) > 三目运算符 > 赋值运算符 > 逗号运算符

针对十进制字面值 :右移数据,相当于除2(unsigned左填0,signed左边填原来的最高位(因为负数移位还要是负数))

     

三、语句

简单语句:;,只有一个分号的空语句。 复合语句:由{}大括号嵌套起来的语句,空块(括号里什么都没用)等于空语句。

(一)条件语句 1、if语句

if语句一般格式:if…else if…else(翻译为如果…否则如果…否则)

if (age>18) { // 如果年龄大于18岁 } else if(age // 上面的都不满足 }

可用搭配: if... if...else if... if...eles... if...else if...else if...else...

tips: (1)if依据后面的条件语句的结果进行判断,非0为真,0为假 (2)else不需要接条件 (3)if语句后面不要接;

2、switch语句

switch语句一般格式:

switch(ch){ // switch是传入整数并判断整数进行判断 case 'a': ... break; case 'b': ... break; default: ... }

tips: (1)case只是入口,所以每个case都要用break;跳出 (2)default类型if语句中的else,即上面的case都不满足时进入 (3)switch只能传入整数进行判断,上面的例子就是将char类型的ch转换成了ASCII码进行比较 (4)switch后面不要接;

(二)迭代语句 1、while语句

while语句的一般格式:

while(条件){ 语句 }

tips: (1)while适用于不知道次数的循环 (2)while后面不要接;

2、do while语句

do while语句的一般格式:

do{ 语句 }while(条件);

tips: (1)do while适用于不知道次数且要先做一遍的循环 (2)do while后面要接; (3)do while后面要接; (4)do while后面要接;

3、for语句

for语句的一般格式:

for (初始化变量; 条件; 变量操作) { 语句 } int n=10; // 定义循环次数 // 例子1,循环n次 for (int i=0; i ; // 语句 i++; } // 例子2,多参数 for (int i=0, j=10; i ; // 语句 i++; j--; }

tips: (1)for适用于知道次数的循环 (2)for后面不要接; (3)for可以压缩行数,简化部分使用while的情况

(三)跳转语句

break;直接跳出当前条件语句或迭代语句,能且只能 跳出 当前 的 一个 语句。   continue;在 条件语句 中表示什么都不做(替代空语句);在 迭代语句 中表示 直接进入下一轮循环,不执行完当前循环 。   goto;跳转到指定位置(该位置必须有声明),例子:

start: // goto声明 ... // 语句 ... // 语句 ... // 语句 goto start; //跳转到start声明位置

!!!注意,goto仅推荐用于跳出多重循环,例如:

for (int i=0; i for (int k=0; k goto end; } } } } end:

     

四、函数 (一)函数一般格式 返回值类型 函数名(形参列表) { ...语句... return 返回值; } // 例子,main函数 int main(){ return 0; }

tips: (1)特殊的返回值类型void(什么都不返回),此时return 返回值;写为return;。 (2)形参列表为空时,表明不需要传入函数。

(二)函数声明

函数声明一般写在程序开头。尽管部分c语言编译器没有要求在调用函数时,就要知道函数格式。但是让编译器提前知道格式,就可以在编译时进行检查,防止我们错误使用了函数。

有一函数定义如下:

int f(int a){ return a; }

那么函数的声明可以写成:

int f(int a); 或者 int f(int);

特殊的对于返回值和参数都是void的函数,声明可以写成:

void f(void);

(三)结构体中的函数

如果能在结构体中写函数,那么结构体就更接近一个类了,例子如下:

struct SHOWDATE{ void (*show)(int year, int month, int day); }; static void show(int year, int month, int day){ printf("%d-%d-%d", year, month, day); } static SHOWDATE showDate={.show=show}; int main(){ showDate.show(2020, 1, 1); return 0; }

     

五、指针 (一)定义 int a=10; int *p=&a; // (1)(2) *p = 12; // (3) int * const p1; // (4) const int * p2; // (5) int const * p3;

(1)*代表这是一个指针类型。具体到例子中就一个int*类型,代表p存放一个指向int类型的地址

(2)&代表取地址。在例子中就是取int类型变量的地址,即变量a的地址

(3)*p代表一个变量,这个变量就是p所指地址里面的变量

(4)int * const p1;不能修改p里的地址

(5)const int * p2;和int const * p3;不能修改p里地址对应的值  

(二)结构体与指针 typedef strcut stDATE{ int year, month, day; } DATE; int main(){ DATE date1={2020, 1, 1}; DATE* date2=&date1; date1.year=2019; date2->month=2; printf("%d-%d-%d", date1.year, date1.month, date1.day); return 0; }

(1)结构体变量访问结构体成员使用.,结构体指针变量访问结构体成员使用->。  

(三)数组与指针 int a[10] = {0} // (1)、(2) int *p = a; // (3) void *q = (void*)p; // (4) int *new = (int*)malloc(10*sizeof(int)); // (5) free(new);

(1)int a[10]里面的a实际上是数组第一个变量的地址,所以可以int *p = a;。 (2)*(p+n)与a[n]等价。 (3)int*指针变量加上一个数n,代表指针变量的数值加上n*32(int的bit)得到偏移。 (4)q表示未定的类型(类似char*但不一样)。 (5)使用int*指针变量来创建数组,使用完要free(程序关闭会自动释放,如果程序长时间使用则会造成内存泄露)。

其他: char c[][]错误; char c[][10]正确且限制大小; char *c[]正确,c[n]是一个char*的字符或字符串 char **c正确,一个指向指针的指针

     

六、文件读取 (一)文本文件

函数定义:

FILE* fopen(const char* restrict path, const char* restrict mode); // 打开文件。参数:路径,模式 int fclose(FILE* stream); // 关闭文件 fscanf(FILE*, ...); // 文件读取(类似scanf,只是加了第一个参数,具体在八) fprintf(FILE*, ...); // 文件输出(类似printf,只是加了第一个参数,具体在八)

fopen的mode选项: r:只读 r+:读写,从文件头开始 w:只写,清空或新建 w+:读写,清空或新建 a:追加,追加或新建 …x:只新建,若存在则不能打开(wx、ax等)

例子:

FILE* p=fopen("file", "r"); if(fp) { ... fclose(fp); }

(二)二进制文件

函数定义(打开文件和关闭文件与文本文件一致):

// ptr:读入字符串存放的变量、size*nmemb:读多少字符、stream:文件句柄 size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream); size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream);

二进制文件读写主要是读写结构体,现在不常用,因为可移植性不好,不如读写文件

     

七、编译预处理指令与.h文件 (一)编译预处理指令

在c语言中,所有#开头的语句都是编译预处理指令。 c语言编译经过 .c——处理编译预处理指令——》 .i——c编译器编译成汇编文件——》 .s——生成目标代码文件——》 .o——生成可执行文件——》 #.out / .exe 四步得到可执行文件,第一步就是处理编译预处理指令。

1、# include < stdio.h >

# include 就是将stdio.h文件里面的内容复制到代码里面去  

2、#define 名称 操作(宏定义)

# define被称为宏定义,格式为# define 名称 操作 例子:

#define PI 3.14159 #define cube(x) (x*x*x) int main(){ cube(3); return 0; }

可以用宏定义定义一个变量PI或一个方法cube。

宏定义定义方法看起来很方便,但十分不推荐初学者使用,因为宏定义的方法是没有类型的,而且运算顺序也不好理解(看上面 二、表达式 15个运算等级的表,就知道多复杂了)。

如果确实想用类似宏定义的方式来定义函数,可以使用下面的方法。  

3、(补充)inline内联函数 inline char *dbtest(int a) { return (a % 2 > 0 ? "奇" : "偶"); }

(二).h文件

.h文件主要用来声明对应.c文件里面的变量或函数,把.c文件里面的声明放到.h文件就可以了(全局变量需要加上extern前缀)。

导入标准库时推荐使用,如# include 导入自定声明时推荐使用"",如# include "train.h"

(三)一些常用宏 printf("%d", __LINE__); // 输出当前语句行号 printf("%s", __FILE__); // 输出当前文件名 printf("%s", __DATE__); // 输出编译日期 printf("%s", __TIME__); // 输出编译时间 printf("%d", __STDC__); // 当要求程序严格遵循ANSIC标准时该标识符被赋值为1 printf("%s", __FUNC__); // 输出当前函数名

     

八、常用函数 (一)常用函数

size_t = unsigned int

库名函数定义解释默认size_t sizeof(type_name)返回bytestring.hsize_t strlen(const char *s)返回s的字符串长度(不包括最后的\0)string.hint strcmp(const char *s1, const char *s2)比较两个字符串,返回0:相等; 1:s1>s2; -1:s1


【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭