C语言学习概览

Posted 胖仙人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言学习概览相关的知识,希望对你有一定的参考价值。

为了更好的阅读体验,建议访问博主的语雀知识库进行阅读

 

Part 1 第一个C语言程序

一、创建工程(编译环境VS2019)

①运行VS2019,点击右下方创建新项目,选择C++空项目

②配置项目内容,选择好项目创建的位置

 ③右击名为源文件的文件夹,选择添加新建项,新建C++文件,文件后缀名更改为.c

 ④编写源文件

二、代码内容

>Code Ⅰ

#include<stdio.h>
int main(void)  -- void可以省略,意为main函数不需要参数
{
	printf("Hello World");
    return 0;
}

①库函数

代码中printf()函数为一个库函数,使用库函数时,要在代码头部引入对应的头文件

②头文件 stdio.h

C语言提供的头文件有很多,stdio代表的是和标准输入输出有关的头文件,.h为头文件的后缀名

③主函数

main - 函数名,固定写法,不可改变

( ) - 函数参数

{ } - 代码块,在代码块内编写代码

int - 整型,表示函数调用完之后会返回一个整数

所有的程序都是从main函数的第一行开始运行,即main函数是程序的入口,且一个项目中的所有.c文件中只能有一个main函

④*main函数带参数的写法

int main(int argc,char * argv[]){}

三、*快捷键

Crtl+F5 --> 执行(运行)代码

F10 --> 逐行运行代码


Part 2 数据类型

一、数据类型引入的意义

程序是服务于现实生活中的方方面面的,而生活中的方方面面往往离不开数据,不同的领域对数据的精确度要求也各不相同,如日常购物计算和银行的计算要求的数据精确度是不相同的,所以在C语言中,我们需要引入不同的数据类型,来满足现实生活中不同的需求。

二、计算机中的单位

bit

byte

=8bit

kb

=1024 byte

mb

=1024 kb

gb

=1024 mb

tb

=1024 gb

pb

=1024 pb

三、数据类型及大小

int main()
{
	//如何计算一个类型创建的变量的所占空间的大小
	//sizeof();
	//%d - 指定打印格式为整数
	printf("%d\\n", 100); //以整数形式打印100
	printf("%c\\n", 100); //以字符形式打印100
	printf("%d\\n", sizeof(char));
	printf("%d\\n", sizeof(short));
	printf("%d\\n", sizeof(int));
	printf("%d\\n", sizeof(long));
	printf("%d\\n", sizeof(long long));
	printf("%d\\n", sizeof(float));
	printf("%d\\n", sizeof(double));
	return 0;
}

名称

关键字名

长度(byte)

字符数据类型

char

1

短整型

short

2

整型

int

4

长整型

long

4

更长的整型

long long

8

单精度浮点型

float

4

双精度浮点型

double

8

有了丰富的数据类型,我们就要考虑使用类型的合理性,比如:

定义一个age变量,用来表示人的年龄,而普遍情况下,人的年龄不会超过三位数

int 能表示的有符号数字的范围:-231+1~ 231

short能表示的有符号数字的范围:-215+1~ 215

为了避免浪费空间,选择用short类型创建该变量更为合适

四、ASCll码

数据在计算机中是以二进制形式存储的,但在编码过程中,我们敲在键盘上的都是字符,为了方便存储,我们给每个能在键盘上敲出来的字符都对应唯一的整数值,方便字符存储在计算机中。

我们将这些对应关系汇制成ASCll码表


Part 3 变量

一、定义变量的方法

//变量的定义:
[数据类型] [变量名];
short age;
float weight;

//变量的初始化:
[数据类型] [变量名] = [值];
short age = 18;

//变量的赋值
age = 20;

二、 局部变量和全局变量

①定义:

在代码块内部定义的变量称为局部变量

在代码块外部定义的变量称为全局变量

int g = 10; //全局变量

int main()
{
	int a = 0; //局部变量
}

②局部变量和全局变量的优先度

>Code Ⅰ:定义一个和全局变量重名的局部变量

int g = 10; //全局变量

int main()
{
	int g = 5; //局部变量
    printf("%d",g);
}

此时打印结果为5,即局部变量和全局变量的名字可以相同(不建议),且局部变量优先使用。修改局部变量时不影响全局变量的值。

三、变量的使用

>Code Ⅰ变量相加案例

int main()
{
	//两个整数相加  
	int num1 = 0;
	int num2 = 0;
	//给两个变量输入值
	scanf("%d %d", &num1, &num2);
	//相加
	int sum = num1 + num2;
	//打印求和结果
	printf("%d", sum);

	return 0;
}

四、变量的作用域

①作用域的定义:通俗的说,变量能被使用的范围称为变量的作用域

②局部变量的作用域:

>Code Ⅰ

int main()
{
    {
    	int a = 10;
    }
    printf("%d",a);
}

运行报错:

上述代码中,变量a是定义在3-5行中的代码块中的,所以变量a只能在3-5行的代码块中使用,3-5行的代码块则称为变量a的作用域

>Code Ⅱ:将printf函数放到代码块中

int main()
{
    {
    	int a = 10;
        printf("%d",a);
    }  
}

运行结果

>Code Ⅲ:在main函数内部,把变量的定义放到代码块的外部

int main()
{
    int a = 10;
    {
        printf("%d",a);
    }  
}

运行程序,能够正常打印

简单的说,全局变量的作用域即为变量定义时所在的代码块

③全局变量的作用域

>Code Ⅰ

int a = 100;	//定义全局变量

void test()
{
	printf("函数打印:%d\\n", a);
}
int main()
{
    test();   //调用函数
	printf("main函数打印:%d\\n", a);
	return 0;
}

运行结果:

>Code Ⅱ:在外部文件中定义的全局变量的使用

(1)我们在项目的源文件夹中添加一个 “外部文件.c”文件:

int g_val = 100;

(2)在文件“全局变量.c”文件中编写代码:

//声明外部变量
extern int g_val;

int main()
{
	printf("%d\\n", g_val);
	return 0;
}

运行结果:

由上述两个案例,全局变量定义后在整个项目内都可以使用;跨文件使用时全局变量时,需要先声明外部变量再使用。

五、变量的生命周期

①局部变量的生命周期

进入局部变量所在的代码块,生命周期开始;出代码块,生命周期结束

②全局变量的生命周期

全局变量的生命周期=程序的生命周期=main函数的生命周期

*补充说明:

        一个int型的变量被定义后,计算机会在内存中申请了4byte的空间用于存放变量的值;该变量的生命周期未结束时,程序拥有这块空间的使用权限;变量的生命周期结束时,这块空间即被回收,用于计算机的其他工作。


Part 4 常量

一、常量的分类

①字面常量

平时看到的数值即为字面常量,如3.14,100等;

int a = 10,即变量a被定义时,将字面常量10这个值存入变量a中。

②const修饰的常变量

一个变量被初始化之后,可以在后面的代码中改变其值,而如果用const修饰该变量,这该变量具有常属性,其初始化的值不能被更改

>Code Ⅰ

int main()
{
	const int a = 100;
    a = 200;
    printf("%d\\n",a);
}

运行报错:

注意:变量a被const修饰之后只是具有了常属性,其本质还是一个变量,并不是变成了一个常量。

③#define定义的标识符常量

>Code Ⅰ

#define Max 200
int main()
{
	int a = MAX;
    printf("%d\\n",a);
}

运行结果:

④枚举常量

生活中一些属性的值可以逐一列举出来,C语言中即可以创建枚举类型来描述这些属性

如:

性别可分为:男 女 保密

>Code Ⅰ

enum Sex   //枚举类型
{
    //枚举的可能取值 - 枚举常量
	MALE,
    FEMALE,
    SECRET
};
int main()
{
	enum Sex s = SECRET;
    printf("%d\\n",s);
    printf("%d\\n",MALE);
    
    return 0;
}

运行结果:

我们定义了一个枚举类型,用来描述性别这个属性,其可能取值有三个,此时我们定义枚举类型的变量时,变量的类型即为enum Sex;

且从运行结果可以看到,当我们打印枚举类型中的值时,可以得到结果为一个常量,

即每个枚举常量都对应一个值,且第一个默认为0,往下依次增加;

因为枚举常量属于常量,所以定义之后也不可在主函数中修改其对应的值(如在主函数写MALE = 3; )

如果我们需要枚举常量对应我们想指定的值,需要在初始化过程中完成

>Code Ⅱ

enum Sex   //枚举类型的初始化过程
{
	MALE = 1,   //为枚举常量赋初值
    FEMALE = 3,
    SECRET = 5
};
int main()
{
	printf("%d\\n%d\\n%d\\n",MALE,FEMALE,SECRET);
    return 0;
}

运行结果:


Part 5 字符串

一、字符与字符串

C语言数据类型分类中,有字符类型,关键字为char,大小为1byte。在编译器中,我们用单引号引出一个字符,如:'a'

但C语言中没有字符串类型的但我们可以用双引号引出一串字符,称之为字符串,如 "abcd"

二、字符串的使用&字符串的结束标志

①一般情况下,我们在使用字符串之前,会先将其存入一个字符数组

CodeⅠ中创建一个能存放10个字符的字符数组,将字符串"abcdef"存入数组中,字符串中的每一个字母视为一个字符,且当字符串存入数组之后,字符串的末尾会默认带上一个结束标志 '\\0'

所以此时,字符串存入数组之后,需要占用7个字符空间,而未被占用的空间会默认存放空字符 '\\0'

>Code Ⅰ

int main()
{
	char ch[10] = "abcdef";
    return 0;
}

调试环节:

①F10逐行运行代码,使代码运行至数组初始化的下一行

②选择菜单栏的调试-->窗口-->监视-->监视1,点击添加要监视的项,输入数组名ch,得到数组中存放值的具体详情

★要重点注意的是,当字符串存入字符数组中时,会自带一个隐藏的结束标志'\\0',需要和数组默认存放的'\\0'区分开。

②为了更直观的观察字符串自带的结束标志,Code Ⅱ中创建字符数组时不定义数组的长度,使数组可以随着字符串长度扩充,这种做法的好处是不会造成空间浪费。

>Code Ⅱ

int main()
{
	char ch1[] = "abcdef";
    return 0 ;
}

调试监视结果:

可以看到,除了我们想要存放的字符串,还多了一个'\\0'

③字符串的输出

在之前的学习中,%d表示以整型输出;%c表示以字符形式输出;

打印字符串时,%s表示以字符串形式输出。

>Code Ⅲ

int main()
{
	char ch[10] = "abcdef";
    printf("%s\\n",ch);
    return 0;
}

运行结果:

三、结束标志'\\0'的影响

①以单个字符形式往字符中存入字符串

>Code Ⅰ

int main()
{
	char ch1[] = {'a','b','c','d','e','f'};
    return 0;
}

监视结果:

 可以发现,以单个字符形式将字符串存入数组时,结尾并没有结束标志'\\0'

②两种形式存放字符串的打印结果比较

>Code Ⅱ

int main()
{
	char ch1[] = "abcdef";
    char ch2[] = {'a','b','c','d','e','f'};
    printf("单字符形式存入数组:%s\\n",ch1);
    printf("字符串性质存入数组:%s\\n",ch2);
    return 0;
}

运行结果:

从结果可以看出,当我们以单字符形式将字符串存入数组后,打印该数组会输出我们预期之外的内容

出现上述结果的原因:

使用printf函数打印字符数组中的字符时,会先读取数组中的内容,读取到第一个'\\0'之后,将其视作为一个结束标志,不再往后读取,并将之前所读取的内容以一串字符的形式打印输出。

而以单字符形式存入时,printf函数在读取完abcdef这6个字母之后,由于没有读取到结束标志'\\0',所以会继续读取数组空间之外的其他内容,直到读取到结束标志'\\0'时停止读取,输出内容。所以得到的结果中,会多出预期之外的随机值

③从求字符串长度来体会结束标志的影响

字符串存入数组之后,想求其长度(即在内存中所占的大小),需要用到strlen()函数;因为strlen是库函数,使用前需要引入对应的头文件;代码如下:

>Code Ⅲ

#include<string.h>   

int main()
{
	char ch1[] = "abcdef";
    char ch2[] = {'a','b','c','d','e','f'};
    printf("ch1的字符串长度:%d\\n",strlen(ch1));
    printf("ch2的字符串长度:%d\\n",strlen(ch2));
    return 0;
}

输出结果:

在数据类型里学过,一个字符的长度为1byte;计算字符串长度,只会将结束标志'\\0'前的字符计入长度,结束标志本身不计入字符串长度;所以代码中字符串正确的长度应为6byte。

而以单字符形式存入字符串时,由于会一直读取到结束标志为止,所以计算长度时,也将多出来的随机值计入了长度。


Part 6 转义字符

一、案例

写一个程序,期望它能打印一串文件路径,而文件路径中是有'\\'来划分层级的,代码如下:

>Code Ⅰ

int main()
{
	printf("C:\\test\\test.c");
	return 0;
}

打印结果:

可以看到,打印结果和预期结果并不一样,路径中的'\\t'并没有成功打印。这是因为,'\\t'在C语言中,是一个转义字符

二、转义字符的使用

顾名思义,转变一个字符原本的含义,通过一下代码,进一步了解转义字符:

①printf函数的打印规则:printf()函数会将括号内双引号引起的内容打印输出;

>Code Ⅰ

int main()
{
	printf("第一行:%dn",100);
    return 0;
}

运行结果:

上述代码中,期望以整数的形式打印100;打印时,100会以整数形式替换%d的位置,其他内容按照printf函数打印规则,双引号内的内容会被打印,打印结果应为图片所示结果

②当我们在字符 'n' 前加上字符 '\\' 后:

int main()
{
	printf("第一行:%d\\n",100);
    return 0;
}

运行结果:

打印结果中,并没有 '\\n' 的出现

此时,'\\n' 这个整体已经是一个转义字符了,在打印时实现其对应的功能;

转义即转变了字符n本身的含义,使其变成了一个具有功能性的字符,所以被称之为转义字符;

'\\n' 在C语言中为具有换行功能的转义字符转义字符的

③转义的核心

不难看出,转义字符中起到“转义”作用的其实是转义字符之前的反斜杠 '\\' ;即在一个字符前加上反斜杠会转变该字符原有的含义。

比如 '\\n' 表示换行符;'\\t' 表示水平制表符等;

需要额外说明的是C语言中的单引号和双引号:

写一个程序预期输出双引号引起的HelloWorld;即"HelloWorld";按照printf函数的打印规则,写出如下代码。

>Code Ⅰ

int main()
{
	printf(""HelloWorld"");
	return 0;
}

程序报错:

程序不能正常运行,其原因在于C语言中双引号和单引号都是用来引起一段内容的,它门会自动寻找配对;

如上述代码中,我们期望中间的两个双引号以及引起的字符串HelloWorld能被输出,但实际上第一个双引号和第二个双引号会自动配对,作为一对双引号,行使其作为双引号引起内容的职责;第三个双引号和第四个双引号亦是同理。

所以夹在中间的字符串HelloWorld实际上和它两侧的双引号并不是一个整体,这样的写法是不符合C语言语法的。

为了解决这个问题,我们在双引号前加上反斜杠'\\',构成转义字符 \\" ,使其不再具自动配对并引起内容的特性,而是单纯的作为一个字符。

>Code Ⅱ

int main()
{
	printf("\\"HelloWorld\\"");
	return 0;
}

输出结果:

单引号同理。

④反转义

既然反斜杠是转义的核心所在,可以转变字符原本的含义,同理,在反斜杠之前加上反斜杠,亦可使其失去转义的功能;在转义字符前加上反斜杠,使其变为纯字符,失去转义字符的功能;

回到开头打印路径的案例,我们在转义字符\\t前加上反斜杠\\\\t,此时\\t就不再是水平制表符了,而是作为纯文本字符:

>Code Ⅰ

int main()
{
	printf("C:\\\\test\\\\test.c");
	return 0;
}

输出结果:

三、转义字符\\ddd和\\xdd

①转义字符\\ddd,表示1~3位八进制数所代表的字符

如/065,表示八进制数065代表的代表的字符

计算过程:

065 --转换成10进制--> 53 --做为ASCAll码值对应的字符--> 字符5

>Code Ⅰ

​int main()
{
	printf("%c\\n",'\\65');
    return 0;
}

运行结果:

②\\xdd,表示1-2为十六进制数所代表的字符

用法和\\ddd同理

四、计算字符串长度案例(转义字符的判断)

转义字符在计算长度时,只作为一个字符来处理,其大小为1byte

>Code Ⅰ:求字符串长度

int main()
{
	printf("%d\\n",strlen("C:\\test\\328\\test.c"));
}

输出结果:

字符拆解:

'C' , ':' , '\\t' , 'e' , 's' , 't' , '\\32' , '8' , '\\t' , 'e' , 's' , 't' , '.' , 'c'

易错点:\\ddd后面跟的数字必须是8进制数字(<8),所以\\328是两个字符。


Part 7 注释

一、注释的作用

注释的文本是不会被编译器识别编译的,在编译器中呈绿色字体;一般用于为某段注释信息添加解释说明;或者用于屏蔽程序中暂时不需要的代码

二、注释语法

①单行注释(C++注释风格):双斜杠后跟注释内容//

int main()
{
    int a = 0; //(单行注释)定义变量a
	return 0;
}

②多行注释(C语言注释风格):/*注释内容*/

int mian()
{
	/*程序的功能
	1:……
    2:……
    */
    int a = 0;
    return 0;
}

三、VS2019中相关快捷键

①选中需要注释的代码:Crtl+K+C 快捷注释

②选中已被注释的代码:Crtl+E+U 取消注释


Part 8 选择语句

一、初见分支

生活中最常见的例子就是使用支付软件时选择是否支付,简单实现一下这个过程:

>Code Ⅰ

int main()
{
	int input = 0;
    printf("确认支付?(1/0):");
    scanf("%d",&input);
    
    if(input == 1)
    {
    	printf("支付成功\\n");
    }
    else if(input == 0)
    {
    	printf("支付失败\\n");
    }
    return 0 ;
}

运行结果:

ps:深入学习将放在正式章节中介绍


Part 9 循环语句

一、初见循环

利用循环实现一个简单的计数,当数字加到100时,就停止程序:

>Code Ⅰ

int main()
{
	int a = 0;
    while(a<100)
    {
        a ++;
    	printf("计数:%d\\n",a);
    }
    return 0;   
}

运行结果:

ps:循环有多种形式,深入学习将放在正式章节中介绍


Part 10 函数

一、初见函数

函数可以封装某个功能,比如之前学习的两数求和案例,改写成用函数实现:

>Code Ⅰ

int Add(int x, int y)
{
	return x+y;
}
int main()
{
	int x = 0;
    int y = 0;
    int sum = 0;
    scanf("%d %d",&x,&y);
    sum = Add(x,y);
    printf("两数和为:%d",sum);
    return 0;
}

运行结果:

我门将求和这个功能封装进了add这个函数中,这时候我们只要给这个函数提供我们要求和的数,函数就会计算得出结果,并将结果返回到主函数中。


Part 11 数组

一、数组的定义

数组中存放了一组相同类型元素的集合。当我们编码时需要用到多个相同类型的数据时,我们可以考虑用数组来存放这些数据

int main()
{
	int arr[10] = {1,2,3,4,5,6,7,8,9,10};//
    return 0;
}

数组的定义方法:

数据类型 数组名[n] = { };

数组定义时:

①需要定义该数组存放的是什么类型的数据。上述代码中,创建的数组只能存放int类型的数据;

②需要定义数组名。上数代码中,arr即为数组名

③数组名后要接中括号,且中括号内要填入整型常量,表示数组空间的大小。上述代码中,该数组能存放10个int型数据

④赋予初值是,在‘{ }’中写要存入数据的数据。上述代码总,数组中存放了1~10的整数

二、数组的使用

①数组的下标:

数组被创建时,数组的每个空间都有一个编号,该编号默认从0开始递增。如上述代码中,数组中元素3对应的数组下标为2;

知道下标后,我们可以使用数组名[下标]的形式来访问数组中的每个元素

>Code Ⅰ

int main()
{
	int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    printf("%d %d",arr[1],arr[9]);
    return 0;
}

运行结果:

因为数组的下标时默认从0开始增长的,所以该代码中,arr[1]访问的是数组中第二个元素,arr[9]访问的是第10个元素

数组的最大下标 = 数组长度 - 1

②利用循环遍历数组

int main()
{
	int i = 0;
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    while(i<10)
    {
    	printf("%d",arr[i]);
        i++;
    }
    return 0;
}

运行结果:

当我们想要访问数组中元素时,下标部分是可以为变量的,如上述代码中下标为 i ,其值是一直在变的;但要注意的是,定义数组时,数组名后括号内的数字必须为整型的常量,不可为变量。


Part 12 操作符

一、操作符的分类

①算数操作符

+

-

*

/

%

取余数

加减乘操作符的用法比较简单,这里对除法做一些说明:

当除法的两边都为整数时,其运算结果只会取结果的整数。

>Code Ⅰ

int main()
{
 	int a = 5 / 2;
    float b = 5 / 2;
    printf("%d\\n%f\\n",a,b);
    
    return 0;
}   

运行结果:

可以看到,不管存放结果的变量是什么类型,其结果只会取5除以2结果的整数部分

实际上,只要除号两边都是整数时,只会取算式答案的整数部分作为结果;

只要有一边为浮点数时,结果才会取小数部分,存放结果的变量类型需为浮点型

>Code Ⅱ

int main()
{
    float a = 5 / 2.0;
    printf("%f\\n",a);
    
    return 0;
}   

运行结果:

②移位操作符

>>

右移操作符

<<

左移操作符

移位操作符是在二进制条件下进行运算的:

>Code Ⅰ

int main()
{
	int a = 6;
    int b = a<<1;
    printf("%d\\n",b);
    return 0;
}

运算过程:

移位操作符在二进制条件下运算的:

(1)二进制转换:

对a的值6进行左移操作时,需要先将6转换成二进制

6 --二进制--> 110;

(2)补位:

因为a是整型变量,所占大小为4字节;

1字节=8bit,共32bit,一个二进制数占1bit,所以用二进制数运算时,先用0补满32位

  |0000 0000 0000 0000 0000 0000 0000 0110|;

(3)移位操作:

进行左移操作,将整个二进制数往左移一位

0|0000 0000 0000 0000 0000 0000 0000 110 |;

(4)溢出丢弃,空位补0:

右边空出的位补上0,左边的一位丢弃,得到移位后的二进制数:

  |0000 0000 0000 0000 0000 0000 0000 1100|;

(5)十进制转换:

将新的二进制数转换回十进制,得到十进制数12,运算结束

运行结果:

③位操作符

&

按位与

^

按位异或

|

按位或

>Code Ⅰ:按位与

int main()
{
	int a = 3;
    int b = 5;
    int c = a & b;
    printf("%d",c);
	return  0;
}

运算过程:

和移位操作符相同,位操作符也是运算于二进制条件下的

(1)二进制转换:

3 --二进制--> 11;

5 --二进制--> 101;

(2)补位:

0000 0000 0000 0000 0000 0000 0000 0011

0000 0000 0000 0000 0000 0000 0000 0101

(3)对应位进行按位与

两数补满32位后,使两数对齐,每一位相对

上下相对的两个数中:只要有0,则该位上按位与得到的结果为0;当同为1时,该位上按位与得到的结果位1

0000 0000 0000 0000 0000 0000 0000 0011

0000 0000 0000 0000 0000 0000 0000 0101

按位与之后:

0000 0000 0000 0000 0000 0000 0000 0001

(4)十进制转换:

将得到的按位与结果转换回十进制,得到结果1;

运行结果:

>Code Ⅱ:按位异或

int main()
{
	int a = 3;
    int b = 5;
    int c = a ^ b;
    printf("%d",c);
	return  0;
}

运算过程:

(1)前三步和按位与操作相同

(2)对应位进行按位异或

按位异或运算:对应位两数相同,得到结果为0;对应位两数相异,得到结果位1

0000 0000 0000 0000 0000 0000 0000 0011

0000 0000 0000 0000 0000 0000 0000 0101

按位异或后:

0000 0000 0000 0000 0000 0000 0000 0110

(3)十进制转换

将得到的结果转换成十进制,得到结果6;

运行结果:

>Code Ⅲ:按位或

int main()
{
	int a = 3;
    int b = 5;
    int c = a | b;
    printf("%d",c);
	return  0;
}

运算过程

(1)前三步同按位与

(2)对应位进行按位异或

按位或运算:对应位的两个数中,只要有1,得到的结果即为1

0000 0000 0000 0000 0000 0000 0000 0011

0000 0000 0000 0000 0000 0000 0000 0101

按位异或后:

0000 0000 0000 0000 0000 0000 0000 0111

(3)十进制转换

将得到的结果转换成十进制,得到结果7

运行结果:

④赋值操作符

=

赋值操作符

+=

复合赋值

-=

*=

/=

&=

^=

|=

>>=

<<=

(1)赋值

定义一个变量时并给予变量一个值,如:

int a = 10;

该过程称为a的初始化,即定义变量a的时候,使其初识值为10;

如果在后续使用到该变量并需要改变其值时,如:

a = 20;

该过程则称为赋值

(2)复合赋值

以+=举例,其作用可以简化表达式

a = a+1;

该表达式可等价为:

a += 1;

其他的复合赋值同理

⑤单目操作符

!

逻辑反操作

-

负值(和数学理解相同)

+

正值

&

取地址

sizeof

操作数的类型长度

~

对一个数的二进制按位取反

--

前置,后置--

++

前置,后置++

*

间接访问操作符(解引用操作符)

(类型)

强制类型转换

前面所介绍的操作符,使用时需要两个操作符,才能使运算关系成立

如:

int c = a + b;

其中a和b就是+的两个操作数。

而只有一个操作数的运算符,则被称为单目操作符

>Code Ⅰ:逻辑反操作符

int main()
{
	int a = 10;
    int b = 0;
    printf("%d\\n",!a);
    printf("%d\\n",!b);
    
    return 0;
}

C语言中,强调真和假;0代表假,非0则为真;且如不特别赋值,默认的真值为1
上述代码中,变量a此时也可以视作为表示真,变量b可视作表示假

分别对a和b进行逻辑反操作后:

!a 此时则表示为假,输出结果应为0

!b此时则表示为真,输出结果应为默认真值1

运行结果 :

>Code Ⅱ:sizeof

int main()
{
	int a = 10;
    printf("%d\\n",sizeof(a)); //计算变量a所占空间的大小
    printf("%d\\n",sizeof(int)); //计算int类型创建的变量所占的空间大小
    return 0 ;
}

运行结果:

补充知识——原码、反码和补码:

一个整数的二进制有3中形式:原码、反码、补码

正整数的三码相同,负整数的三码是需要计算的

以正整数1举例:

其二进制为:

0000 0000 0000 0000 0000 0000 0000 0001

根据十进制与二进制之间的转换规则,计算得到的二进制,称为原码,其最高位为符号位,0代表正数,1代表负数

由于正整数三码相同,由此得到

反码:

0000 0000 0000 0000 0000 0000 0000 0001

补码:

0000 0000 0000 0000 0000 0000 0000 0001

再看负数的情况,以负整数-1举例:

根据转换规则得到原码:

1000 0000 0000 0000 0000 0000 0000 0001

符号位不变,其他位按位取反,得到反码:

1111 1111 1111 1111 1111 1111 1111 1110

反码+1,得到补码:

1111 1111 1111 1111 1111 1111 1111 1111

要注意的是,整数存储在计算机中时,是以补码形式存储的;运算时,用的也是补码二进制序列

>Code Ⅲ:~按位取反

int main()
{
	int a = 0;
    printf("%d\\n",~a);
}

运算过程:

(1)0的补码:

0000 0000 0000 0000 0000 0000 0000 0000

(2)按位取反得到运算结果的补码:

1111 1111 1111 1111 1111 1111 1111 1111

(3)我们能够读懂的时原码,所以将补码计算得到原码:

补码-1 --> 反码按位取反 --> 原码

1000 0000 0000 0000 0000 0000 0000 0001

(4)转换成十进制,得到结果-1

运行结果:

>Code Ⅳ:-- 和 ++

int main()
{ 
	int a1 = 2;
    int a2 = 2;
    int b = ++a1;
    int c = a2++;
    printf("b的值为:%d\\n",b);
    printf("c的值为:%d\\n",c);
    printf("a1的值为:%d\\n",a1);
    printf("a2的值为:%d\\n",a2);
    return 0;
} 

前置++和后置++的区别:

为了方便记忆,记住就近原则

如果++的操作数离=比较远,如代码中的a1,则在赋值给b时,先自增,再赋值;即b的结果位3

如果++的操作数离=比较进,如代码中的a2,则再赋值给c时,先将a2原来的值赋给c,再自增;即c的结果为2

而不管a1还是a2,程序运行结束时都自增了。前置--和后置--同理。

运行结果:

⑥关系操作符

>

大于

>=

大于等于

<

小于

<=

小于等于

!=

不等于

==

等于

⑦逻辑操作符

&&

逻辑与(并且)

||

逻辑或(或者)

>Code Ⅰ

int main()
{
	int a = 3;
    int b = 4;
    //如果a=3并且b=4,就打印HelloWorld
    if((a==3) && (b==4))
    {
    	printf("HelloWorld");
    }  
    //如果a=3并且b=4,就打印C语言
    if((a==3) && (b==5))
    {
        printf("C语言");
    }
    return 0;
}

逻辑与操作符相当于生活中说的并且,需要条件都满足时,才能继续执行后续的代码;

上述代码中,a的值为3,b的值为4,不能满足a=3并且b=5,所以“C语言”不会被打印;

运行结果:

>Code Ⅱ

int main()
{
	int a = 3;
    int b = 4;
    //如果a=3或者b=4,就打印HelloWorld
    if((a==3) || (b==4))
    {
    	printf("HelloWorld\\n");
    }  
    //如果a=3或者b=4,就打印C语言
    if((a==3) || (b==5))
    {
        printf("C语言\\n");
    }
    //如果a=2或者b=5,就打印C++
     if((a==2) || (b==5))
    {
        printf("C++");
    }
    return 0;
}

逻辑或操作符相当于现实中说的或者,只要多个条件中满足一个条件,就能继续执行相应的代码

上述代码中,只有最后一个打印C++是a和b的值都不满足的,所以不会打印C++

运行结果:

⑧条件操作符(三目操作符)

exp1 ? exp2 : exp3

>Code Ⅰ:写一个简单的分支逻辑

int main()
{
	int a = 10;
    int b = 0;
    //分支逻辑:
   	//如果a等于5,就将-6赋值给b;否则将6赋值给b
    if(a==5)
   	{
    	b = -6;
    }
    else
    {
    	b = 6;
    }
    
    return 0 ;
}

运行结果:

CodeⅠ中的代码,可以通过条件操作符更简洁的实现

>Code Ⅱ

int main()
{
	int a =10;
    int b = 0;
    b = (a == 5) ? -6 : 6;
    return 0;
}

CodeⅡ中,问号前的表达式1为我们需要判断真假的表达式;若表达式1的值为真,则取表达式2结果作为整个表达式得结果;否则取表达式3作为整个表达式的结果

运行结果:

⑨逗号表达式

exp1,exp2,exp3...

>Code Ⅰ

int main()
{
	int a = 0;
    int b = 3;
    int c = -1;
    int d = (a = b - 5, b = a + c , c = a + b , c -= 5);
    pritnf("%d\\n", d);
}

上述代码将一个逗号表达式的结果赋值给变量d,逗号表达式会从左向右依次计算;逗号表达式的最后一个结果被作为整个表达式的结果。

计算过程

(1)a = b-5 --> a = -2,b = 3,c = -1

(2)b = a+c -->a = -2,b = -3,c = -1

(3)c = a+b -->a = -2,b = -3,c = -5

(4)c -= 5 -->a = -2,b = -3,c = -10

因为c -= 5

以上是关于C语言学习概览的主要内容,如果未能解决你的问题,请参考以下文章

C语言学习概览

C 语言编程 — 数据类型概览

C 语言编程 — 数据类型概览

我的C语言学习进阶之旅解决 Visual Studio 2019 报错:错误 C4996 ‘fscanf‘: This function or variable may be unsafe.(代码片段

我的C语言学习进阶之旅解决 Visual Studio 2019 报错:错误 C4996 ‘fscanf‘: This function or variable may be unsafe.(代码片段

需要示例代码片段帮助