C语言第二章 数据类型,常量与变量,操作符

使用计算机是为了解决一些生活中的问题,解决问题必然需要进行数据的处理。C语言提供了丰富的数据类型和操作符来描述与处理数据。

2.1数据类型

C语言中的数据类型如下图,本文主要介绍内置数据类型
在这里插入图片描述

2.1.1内置数据类型

C语言中的内置数据类型有字符型,整型,浮点型,布尔类型。想要创建一个数据,需要使用对应的类型进行数据声明,整型使用int,字符型使用char,浮点型使用float。其中,整型分为短整型(short),整型(int),长整型(long),更长的整型(long long),浮点型包括单精度(float),双精度(double),扩展精度浮点数(long double)。布尔类型比较特殊,想要在C语言中使用布尔类型,需要包含头文件<stdbool.h>,0表示false,任何非零值表示true。
C语言中每一种数据类型都有自己的长度,使用不同的数据类型,可以创建出长度不同的变量。可以使用sizeof关键字来计算每一种数据类型的长度,单位为字节。通过下面的代码,可以在VS2022上输出每种数据类型在内存中所占的大小,其中%zd为占位符,下文会进行介绍

#include <stdio.h>
int main()
{
	printf("char length:%zd\n", sizeof(char));
	printf("bool length:%zd\n", sizeof(_Bool));
	printf("short length:%zd\n", sizeof(short));
	printf("int length:%zd\n", sizeof(int));
	printf("long length:%zd\n", sizeof(long));
	printf("long long length:%zd\n", sizeof(long long));
	printf("float length:%zd\n", sizeof(float));
	printf("double length:%zd\n", sizeof(double));
	printf("long double length:%zd\n", sizeof(long double));
	return 0;
}

运行结果
在这里插入图片描述

2.1.2数据类型的取值范围

在C语言中,由于数据都是以二进制进行存储,所以每种数据类型所占的二进制位就决定了对应的数据类型的取值范围。下面给出整型和字符型的取值范围,当然,浮点数也有范围,不过没有很多的实践意义
在这里插入图片描述

可以看到每种数据类型都有自己的取值范围,所以在存储数据时,应当根据实际情况来定义相对应的数据类型,注意不要超出范围。

2.1.3signed和unsigned

在上面数据类型的范围中,出现了两个新的关键字,就是signed和unsigned。C语言使用signed和unsigned关键字修饰字符型和整型类型的。signed表示一个类型带有正负号,包含负值。unsigned表示该类型不带有正负号,只能表示零和整数。上面不加修饰所声明的整型变量默认为有符号的整型。此时关键字signed可以省略不写,但写了也不算错。根据上面的取值范围可以发现一个有趣的现象,unsigned修饰的变量类型所能表示范围的最大值为signed修饰的变量类型所能表示范围最大值的2倍,实际上这一点跟数据在内存中的存储有关,在后续的文章中会进行介绍。

2.1.4sizeof关键字的一些特性

  • sizeof的操作数如果不是类型,是表达式的时候可以省略括号。
  • sizeof后面的表达式不参与运算,是根据表达式的类型来得出大小。
  • 为了便于移植,sizeof的计算结果并非int类型,而是size_t类型的,所以代码中的占位符使用了%zd。
#include <stdio.h>
int main()
{
	int a = 10;
	printf("%zd\n", sizeof(a));
	printf("%zd\n", sizeof a);  //操作数为变量,类型可省略
	printf("%zd\n", sizeof(int));
	printf("%zd\n", sizeof(3 + 3.5));  //表达式不计算,根据类型得出大小
	return 0;
}

运行结果
在这里插入图片描述

2.2常量和变量

数据类型是用来创建变量的,而变量可以用来存储数据,进而去解决一些实际问题。在C语言中,经常变化的值称为变量,不变的值称为常量。

2.2.1变量的创建

想要创建一个变量需要声明它的数据类型,并给出它的名字,语法格式如下
在这里插入图片描述

int a;  //整型变量
char ch;  //字符型变量
float t;  //浮点型变量

在创建时给定一个初始值,称为变量的初始化,如果不对变量进行初始化,那么变量会被编译器赋值为1个随机值,这样可能会出现一些无法掌控的情况,因此为了代码书写格式规范,在创建变量的同时最好对其进行初始化、值得一提的是,在VS2022这个编译器上,未初始化的变量是不允许使用的。

int age = 18;
char ch = 'w';
double weight = 48.0;
unsigned int height = 100;

2.2.2变量的分类

C语言中的变量分为全局变量和局部变量。在大括号外部定义的变量就是全局变量,全局变量的使用范围很广,整个工程中想使用,都是有办法使用的。在大括号内部定义的变量就是局部变量,局部变量的使用范围是比较局限的,只能在自己所在的局部范围内才能使用。

#include <stdio.h>
int global = 2024;  //全局变量
int main()
{
	int local = 2004;  //局部变量
	printf("%d\n", global);
	printf("%d\n", local);
	return 0;
}

如果全局变量和局部变量名字相同,则会优先使用局部变量

#include <stdio.h>
int global = 2024;  //全局变量
int main()
{
	int global = 2004;  //局部变量
	printf("%d\n", global);
	return 0;
}

运行结果
在这里插入图片描述
一般在学习C/C++语言的时候,我们会重点关注内存中的三个区域:栈区,堆区和静态区
1.局部变量存放在内存中的栈区
2.全局变量存放在内存中的静态区
3.堆区是用来进行动态内存管理的
但其实内存的划分是非常细致的,这就要涉及到一些操作系统的知识了,本文暂不进行讨论。
在这里插入图片描述

2.2.3常量

常量也称为字面量,书写格式如下,非常简易。当然也可以在声明变量的时候增加const关键字,将其声明为一个常量。经过const修饰过的变量是不可改变的,强行赋值编译器会进行报错

//常量或者叫做字面量
18;
23.5;
'a';
//这两种声明方式都可以达到同样的效果,一般使用第一种
const int a=10;
int const a=10;

2.3标准输入输出

想要跟计算机互动,并且帮助我们解决实际问题,需要经常进行输入和输出。在C语言初学阶段,经常使用的一组标准输入输出函数就是scanf函数和printf函数。想要使用这两个函数,都必须包含<stdio.h>这个头文件。

2.3.1占位符

在上文的一些小程序中,已经直接的使用过了占位符,所谓占位符,就是这个位置可以用其它值代替。printf函数可以在输出文本中指定占位符。下面的程序中,“今年是%d年\n”是输出文本,里面的%d就是占位符,表示这个位置要用其它值来替换。占位符的第一个符号一律为%,第二个符号为占位符的类型,%d表示该位置用一个整数去替换。

#include <stdio.h>
int main()
{
	int a = 2024;
	printf("今年是%d年\n", a);  //用变量a的值替换前面文本中%d的位置
	return 0;
}

运行结果
在这里插入图片描述
当然,printf函数中的占位符可以不止一个,也可以有多个,%d表示整数,也有其它的占位符,%s表示字符串

#include <stdio.h>
int main()
{
	int year = 2024, month = 6, day = 17;
	char ch[] = "闰年";
	printf("今年是%d年%d月%d日\n", year, month, day);  //多个占位符
	printf("今年是%s\n", ch);  //使用%s格式,用字符串去进行替换
	return 0;
}

运行结果
在这里插入图片描述

2.3.2printf()函数

printf()函数的作用是将参数文本以指定的格式输出到屏幕上,即标准输入。标准输入一般指将对应内容输出到屏幕上,在上文的一些小程序中已经进行过演示。下面介绍一下它对于输出格式的控制。

  • 限定宽度与小数位数
    printf()函数允许限定占位符的最小宽度。在下面的程序中,%5d表示这个占位符的宽度至少为5。如果不满5位,会在前面加上空格,输出默认是右对齐,即输出内容前面有空格。如果想要左对齐,那么需要在占位符的%后面加一个负号
#include <stdio.h>
int main()
{
	int a = 123;
	printf("%5d\n", a);  //默认右对齐
	printf("%-5d\n", a);  //加负号实现左对齐
	return 0;
}

运行结果
在这里插入图片描述
%f表示以浮点数的格式进行打印,但默认保留的小数位数为6位,通常情况下会显得比较冗余,可以在占位符的%后面加上.2,以此来控制保留的小数位数,.后面的数是几,就会保留几位小数

#include <stdio.h>
int main()
{
	float a = 123, b = -69;
	printf("%f\n", a);
	printf("%.2f\n", b);
	return 0;
}

运行结果
在这里插入图片描述
同时限定宽度和保留小数位数也可以同时使用,例如%6.2f表示整个数的宽度为6,小数位数保留2位。同时,这两个参数也可以用*代替,通过printf()函数进行传入

#include <stdio.h>
int main()
{
	float a = 0.4, b = 6.9;
	printf("%6.2f\n", a);
	printf("%*.*f\n", 7, 3, b);
	return 0;
}

运行结果
在这里插入图片描述

  • 总是显示正负号
    printf()函数只对负数显示负号,对正数不显示正号,想要始终显示正号或者负号,可以在占位符的%后面加一个正号,这样可以保证对于任何实数都显示正负号
#include <stdio.h>
int main()
{
	int a = 123, b = -69;
	printf("%+d\n", a);
	printf("%+d\n", b);
	return 0;
}

运行结果
在这里插入图片描述

  • 输出部分字符串
    %s占位符用来输出字符串,默认是全部输出。如果只想输出开头的部分,可以使用格式%.ms指定输出长度,其中m为一个整数,控制输出的长度。通过下面的示例可以清晰的进行演示
#include <stdio.h>
int main()
{
	char ch[] = "hello world";
	printf("%s\n", ch);
	printf("%.5s\n", ch);
	printf("%.1s\n", ch);
	return 0;
}

运行结果
在这里插入图片描述

2.3.3scanf()函数

printf函数的作用是进行标准输出,与之对应的,进行标准输入的函数,就是scanf函数。标准输入一般指的是从键盘进行输入。在C语言程序中,程序执行到scanf()函数这一行后,会等待用户从键盘上输入相应的内容,等到用户输入数据,按下回车之后,会将对应内容存入变量中。想要将数据存入变量中,需要数据类型和变量的名称,指定数据类型与printf()函数类似,使用占位符,所以scanf()函数的语法格式如下,%d表示输入的一个数据为整型,i是要存入的变量,&符号为取地址符号。

scanf("%d",&i);

注意:变量前面必须加上 & 运算符(指针变量除外),因为 scanf() 传递的不是值,而是地址,即将变量 i 的地址指向用户输入的值。如果这里的变量是指针变量(比如字符串变量),那就不用加&符号。
下面的代码中演示了通过使用scanf函数进行多个数据的输入

#include <stdio.h>
int main()
{
	int a = 0, b = 0;
	float c = 0, d = 0;
	scanf("%d%d%f%f", &a, &b, &c, &d);
	printf("a=%d,b=%d,c=%.2f,d=%.2f\n", a, b, c, d);
	return 0;
}

运行结果
在这里插入图片描述
这里要单独说明一下,scanf()函数是有返回值的,表示成功读取变量的个数。如果没有读取任何项,或者匹配失败,则返回 0 。如果在成功读取任何数据之前,发生了读取错误或者遇到读取到文件结尾,则返回常量 EOF。

#include <stdio.h>
int main()
{
	int a = 0, b = 0;
	float f = 0.0f;
	int r = scanf("%d%d%f", &a, &b, &f);
	printf("a=%d b=%d f=%f\n", a, b, f);
	printf("r = %d\n", r);
	return 0;
} 

运行结果
在这里插入图片描述

2.4操作符

C语言中提供了种类繁多的操作符,有着非常强大的数据处理能力。

2.4.1算术操作符

数据之间经常会进行各种四则运算,C语言中与之对应的提供了相应的操作符,即+,-,*,/,%等,其中%为取模运算,作用是求两个数相除之后的余数。需要注意的是,C语言中没有整除运算,如果两个操作数都为整型,那么/操作符进行的就是整除运算,如果其中一个数为浮点数,那么/操作符进行的就是实数之间的除法。
/与%两种运算,经常配合使用处理一些和位数有关的题目,后续的刷题练习文章里会介绍到

#include <stdio.h>
int main()
{
	int a = 18, b = 20, d = 7;
	printf("%d + %d = %d\n", a, b, a + b);  //加法运算
	printf("%d - %d = %d\n", a, b, a - b);  //减法运算
	printf("%d * %d = %d\n", a, b, a * b);  //乘法运算
	printf("%d / %d = %d\n", a, b, a / b);  //除法运算,当操作数均为整型时为整除运算
	float c = 18.5;
	printf("%.2f / %d = %.2f\n", c, b, c / b);  //当其中一个操作数为浮点型时为实数除法运算
	printf("%d %% %d = %d\n", a, d, a % d);  //取模运算,其中%%号的作用是在屏幕上输出一个%号
	return 0;
}

运行结果
在这里插入图片描述
C语言中除了上面5种基本的运算操作符外,还有两种特殊的运算操作符,它们分别是++(自增),–(自减)运算。它们的作用是,对于它们的操作数进行+1的运算,即a++的写法等价于a=a+1。但a++(后置++)和++a(前置++)这两种写法有着一些区别,下面给出一段代码

#include <stdio.h>
int main()
{
	int a = 5, b = 7;
	printf("a++:%d\n", a++);
	printf("a:%d\n", a);
	printf("++b:%d\n", ++b);
	printf("b:%d\n", b);
	return 0;
}

实际上,前置++和后置++实现的最终效果都是对于它们的操作数+1,但放在一些复合语句中,后置++会先将变量a进行使用,使用完之后再++,而前置++会先将变量b进行+1运算,之后再进行使用。–操作符也是同理,这里不再进行演示。
在这里插入图片描述

2.4.2赋值操作符

在C语言中,=的作用是进行赋值操作。将=右边的值赋给=左边的这个变量,在之前的代码中已经进行过演示。这里要介绍几种复合赋值操作符,这类操作符结合了算术操作符,使得写法比较简洁,但实现的还是赋值功能,只不过写法比较简便。下面给出了五种常用的复合赋值操作符:+=,-=,*=,/=,%=。这里主要介绍+=,其余复合赋值操作符都与其类似。下面的代码中,a+=8的写法等价于a=a+8,只不过写法上更加简便,其余复合赋值操作符的功能类似,这里不再过多赘述

#include <stdio.h>
int main()
{
	int a = 10;
	a += 8;
	printf("%d\n", a);
	return 0;
}

运行结果
在这里插入图片描述

2.4.3关系操作符

C语言中有六种常用的关系操作符,用于测试操作数之间的各种关系,这些操作符是:>=,>,<=,<,==,!=。其中前4个操作的功能一看便知,其中 ==操作符用于判断两个操作符是否相等,而!=用于判断不相等。这些关系操作符的返回结果都为整型,1表示真,0表示假。这些操作符经常与逻辑操作符结合起来,在条件判断与循环判断的语句里使用

#include <stdio.h>
int main()
{
	printf("%d\n", 1 >= 2);
	printf("%d\n", 15 < 21);
	printf("%d\n", 1 == 1);
	printf("%d\n", 1 != 2);
	return 0;
}

运行结果
在这里插入图片描述
这里需要额外说明的是,在C语言中,==操作符用于判断操作数是否相等,而=操作符的作用仅仅是赋值,在执行相关功能时,注意不要错用这两个操作符。

2.4.4逻辑操作符

C语言中的逻辑操作符有:&&(与),||(或),!(非)。这些操作符中,&&与||都是用来判断真假的,它们的区别在于,对于下面的两行代码,当操作符&&两边的表达式都为真时,那么它的结果也为真,即结果为1,如果有一个为假,那么返回结果为假,即结果为0。操作符||与&&非常类似,不同的是,当||操作符两边的表达式有一个为真,返回结果就为真,如果两个表达式都为假,那么返回结果为假。

表达式1 && 表达式2;
表达式1 || 表达式2

而操作符!表示对它的操作数执行逻辑反操作,在下面的代码中,如果操作数为真,那么执行结果为假,如果操作数为假,那么结果为真。同样,返回结果为1(真)或者0(假)。

!操作数;

下面的表格对于逻辑操作符进行了简单的梳理
在这里插入图片描述
这里要额外说明的是,&&操作符与||操作符都具有短路求值的行为。那么什么是短路求值呢?以&&操作符举例,当&&操作符左边的表达式,经过计算后发现结果已经为0,那么不管&&操作符右边的表达式是否为真,整个表达式的结果都已经为假,所以&&操作符右边的表达式将不进行计算。||操作符同理。下面这段代码中,由于&&左边的表达式已经为假,所以&&后面的表达式不会进行计算,即b不会执行自增运算

#include <stdio.h>
int main()
{
	int a = 10, b = 20, c = 0;
	c = a > 15 && ++b;
	printf("%d %d\n", c, b);
	return 0;
}

运行结果
在这里插入图片描述

2.4.5条件操作符

条件操作符其实就是一个简化版的选择结构,它的基本用法如下

表达式1 ? 表达式2 : 表达式3;

执行逻辑是,首先会判断表达式1的值是否为真,如果为真,那么整个表达式的结果为表达式2的计算结果,如果为假,整个表达式的结果为表达式3的计算结果。

2.4.6逗号操作符

逗号操作符的基本用法如下

表达式1, 表达式2, ..., 表达式N;

执行逻辑是,这些表达式会自左向右逐个进行求值,整个表达式的结果的值为表达式N的值。
这里的条件操作符和逗号表达式都没有给出具体实例,是因为它们的用法其实非常简单,难的是,在什么场景下适合去使用它们。相比于前面的操作符,你可能会觉得这两个操作符显得有些多余,完全有上位替代,可以不去使用它们。但存在即合理,这两个操作符能被开发出来,就一定有它们对应的使用场景,这就需要在大量的实践中去积累经验,自行体会。

2.4.7强制类型转换

在操作符中还有一种特殊的操作符是强制类型转换,在想要转换的变量前,增加一个(类型)即可。比如,之前提到过,当/操作符的操作数均为整数时,/操作符进行的就是整除运算,如果想进行实数运算,除了将操作数定义为浮点型变量外,还可在运算时对其进行强制类型转换

#include <stdio.h>
int main()
{
	int a = 12, b = 5;
	float c = (float)a / b;
	printf("%.2f\n", c);
	return 0;
}

运行结果
在这里插入图片描述
当然,如果将一个浮点型变量转换为整型,那么将会丢失小数位的数据,可能会造成误差,所以在使用强制类型转换时应当谨慎使用。
本节介绍了许多C语言中常用的操作符,不过除了上述操作符外,C语言还提供了一种特殊的操作符,即位操作符,不过这类操作符的运算逻辑涉及到一些数据在内存中如何存储的知识,这里就先不进行介绍了。

2.5程序举例

例1:编写程序,实现两个数的交换。
分析:实现两个数的交换,必然要用到赋值操作符,在赋值前,为了保存变量,需要第三个变量作为中介,去临时保存数据。

#include <stdio.h>
int main()
{
	int a = 7, b = 8;
	printf("交换前:a=%d,b=%d\n", a, b);
	int t = a;  //借助第三变量来临时存储a的值
	a = b;
	b = t;
	printf("交换后:a=%d,b=%d\n", a, b);
	return 0;
}

运行结果
在这里插入图片描述
例2:输入一个大写字母,实现字母的大小写转换。
分析:有关于C语言中字母大小写的问题,通常都会借助ASCll码值去解决。上一篇文章中介绍过,字符在C语言中是以ASCll码值的形式存储的。查询ASCll码表可以发现,每一对大小写字母之间的ASCll码值的差值为32,将一个大写字母的ASCll值加上32,得到的便是它的小写字母,小写转大写减去32即可。

#include <stdio.h>
int main()
{
	char ch = 0;
	printf("请输入一个大写字母:");
	scanf("%c", &ch);
	printf("该字母的小写字母为:%c\n", ch + 32);
	return 0;
}

运行结果:
在这里插入图片描述
总结一下,本文介绍了很多C语言的基础语法,包括数据类型,常量变量,如何进行输入输出以及很多的操作符。最后的两道编程题,也是在以后会经常用到的算法,学完以上内容,相信读者可以独立编写一些简单的小程序了。

  • 25
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值