第二章C语言数据类型和变量

1.数据类型介绍

我们写代码是为了解决生活中的一些问题,而在解决这些生活中的一些问题时,我们避免不了的
要用代码来表达不同的数据类型,比如说你写一个购物网站的代码,那肯定需要在上面显示
品信息
而这商品信息就是需要数据类型中的字符型来描述,而商品价格132.5元就需要数据类型中的浮点型来描述,当然也有10元这种整数而描述整数,就需要用数据类型中的整型来描述。

所谓类型就是相似数据所拥有的共同特征,比如说整型就是都是整数浮点型就是一些小数字符型则是用来表示字符串或者字符的。计算机只有知道了数据的类型,才知道如何去操作数据。

数据类型又分为:内置类型自定义类型
内置类型则是系统内部自带的类型,可以自接使用,我们接下来要学习的字符型、整型、浮点型、布尔型就是内置类型
自定义类型是需要我们自己创建的类型,这些类型我们以后再学习,现在来跟你们说一下有那些吧,有数组、结构体、枚举、联合体

1.1字符型

关于字符型,前面我们也说了,是用来表示字符串和字符的,那它在代码中怎么表示呢?如下:
char——这个就是字符型
signed char——这个是有符号的字符型。
unsigned char——这个是无符号的字符型。
关于signed 和 unsigned 可以看本章第二节

1.2整型

整型前面也说了,用来描述整数的,那么直接上整型代码了,如下:
int——整型
signed int——有符号整型。
unsigned int——无符号整型。
short int——短整型
signed short int——有符号的短整型。
unsigned short int——无符号的短整型
long int——长整型
signed long int——有符号的长整型
unsigned long int——无符号的长整型
long long int——更长的整型,这个类型是c99标准中引入的
signed long long int——有符号的更长整型
unsigned long long int——无符号的更长整型
有同学看到这就问了:这整型和短整型还有长整型,更长整型,这些都有啥区别?它们的区别就是长度不同,本章1.5节各种数据类型的长度会详细说明。

1.3浮点型

浮点型前面也说了是用来表示小数的数据类型,如下:
float——单精度浮点型
double——双精度浮点型
long double——高精度浮点型
它们的区别就是小数点后精度不一样,float精度最低,long double精度最高

1.4布尔型

布尔型是c99中才引用的数据类型,专门用来表示真假。之前是用0来表示假,非0表示真。
_Bool
使用布尔类型需要包含头文件#include<stdbool.h>
布尔类型变量的取值是true或者false代码演示如下:

#include<stdbool.h>
#include<stdio.h>
int main()
{
	bool a = true;
	if (a)
		printf("haha");
	return 0;
}

1.5各种数据类型的长度

每一种数据类型都有属于自己的长度,因为创建一个变量需要在内存里开辟一个空间,所以使用不同的数据类型来创建变量,就会得到不同长度的空间,变量的长度不同,存储的数据范围也会有所差异。

1.5.1sizeof操作符

sizeof是一个关键字也是操作符,是专门用来计算sizeof的操作数的类型长度的,单位是字节

什么是字节呢?要想知道这个问题,我们还要知道计算机的一些常见单位才能更好的了解字节。计算机的常见单位如下:
bit ——比特位,计算机中最小的单位
byte ——字节,1个字节=8个比特位
kb——1kb = 1024个字节
MB —— 1MB = 1024kb
GB —— 1GB = 1024MB
PB —— 1PB = 1024GB
计算机只能识别二进制数据,所以我们还要了解一下二进制数据长啥样。
众所周知,我们所熟悉的十进制的数据是由0~9数字组成的,逢十进一。所以我们可以推算出二进制的数据是由0
~1组成的,逢二进一!

也就是说计算机只能读取0或者1这俩数据,既然要读取数据肯定要进行存储,而存储一个二进制位(也就是存储一个二进制数)就需要一个比特位的空间。
接下来我们回归sizeof的探讨sizeof的操作数可以说类型,也可以是变量,或者是表达式
sizeof(类型)
sizeof 表达式
sizeof后面如果不是类型是表达式的时候,括号可以省略不写
sizeof后面的表达式是不参与运算的,根据表达式的类型得出大小。
sizeof的计算结果是size-t类型,所以占位符是%zd。
sizeof计算类型大小的代码如下:

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

sizeof后面放表达式的代码如下:

#include<stdio.h>
int main()
{
	int a = 10;
	int b = 0;
	printf("%zd\n", sizeof a);
	printf("%zd\n", sizeof (b = a + 1));
}

sizeof在代码进行编译的时候,就根据表达式类型确定了类型的常用,而表达式的执行,需要在程序运行期间执行,但是在编译期间已经把sizeof处理过了,所以在运行时,sizeof后面的表达式就不会进行运算了

2.signed和unsigned

C语言使用signed和unsigned来修饰字符型整型

signed,是一个关键字,表示这个类型是有符号类型,就是说明这个数据类型带有正、负号。

unsigned ,是一个关键字,无符号类型,表示该类型不具有正、负号,只能表示0和正数。

对于int类型,是默认带有正负号的,也就是说,int 等同于 signed int,由于这种默认情况,signed可以省略不写,写不写都对

int类型也可以不带正负号,只表示非负整数,这个时候就要用的unsigned int来声明变量了。如:unsigned int a = 0;
整数变量声明为unsigned的好处是,如果同样都是表示非负整数的,unsigned的存储空间长度比int(signed int)增大了一倍。(字符型也适用)
unsigned int 可以省略int,变量声明可以写成这样:unsigned a = 0;

字符型char也可以设置signed和unsigned,变量声明如下:signed char c;unsigned char c;注意:char是否带有正负号由当前系统决定,也就是说,char不等同于signed char,它有可能是signed char,也有可能是unsigned char,这一点与int不同

3.数据类型的取值范围

我们在第一节说了那么多数据类型是为什么呢?
因为每个数据类型都有不同的取值范围,也就是存储数据最大值和最小值的区间。有了这些不同的数据类型,我们就可以更好地去选择合适的数据类型来创建不同的变量。
limits.h说明了整型类型的取值范围
float.h说明了浮点型的取值范围

#include<stdio.h>
#include<limits.h>
#include<float.h>
int main()
{
	printf("%d", CHAR_MIN);
	printf("%d", SHRT_MIN);
	printf("%d", INT_MIN);
	printf("%d", LONG_MIN);
	printf("%d", LONG LONG_MIN);
	printf("%d", UCHAR_MAX);
	printf("%d", USHRT_MAX);
	printf("%d", ULONG_MAX);
	printf("%d", ULLONG_MAX);
	return 0;
}

4.变量

4.1变量的创建

我们前面了解那么多数据类型是为什么呢?当然是为了创建变量啊,那什么又是变量呢?在C语言中,把变化的值,称为变量
不变的值称为常量。
变量创建的语法形式如下:数据类型(如int)变量名(变量名可自己取)如:int a;
如果在变量创建的时候给一个初始值,那就是变量初始化,如:int age = 18;

4.2变量的分类

变量分为全局变量局部变量
全局变量:在大括号外部定义的变量就是全局变量。全局变量使用范围很广,整个工程中想要使用它都是有办法使用的
局部变量:在大括号内部定义的变量就是局部变量。局部变量使用范围有限,只能在自己的局部范围内使用

#include<stdio.h>
int a = 2024;//这就是全局变量
int main()
{
	int b = 2025;//这个是局部变量
	printf("%d\n",a);
	printf("%d\n",b);
	return 0;
}

注意:当局部变量和全局变量名字相同时,局部变量优先使用

局部变量和全局变量在内存中存储在哪里呢
我们在学习c/c++时,我们都会观察内存中的三个区域:栈区、堆区、静态区
局部变量是放在栈区的
全局变量是放在静态区的
堆区是放动态内存管理的

5.算术操作符:+、-、*、/、%

写代码解决问题时,一定会碰到计算,C语言为了方便我们运算,提供了一系列操作符,其中就有
算术操作符,分别是:+,-,*,/,%。这些操作符是双目操作符。
*操作符也被叫做运算符,不同的翻译罢了,意思是一样的。

5.1+和-

+和-是用来完成加法和减法的两个运算符,都是有2个操作数的,位于操作符两端就是操作数,这种操作符也叫双目操作符如:

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

5.2*

运算符*是用来完成乘法运算的,不用说我想你们也知道这是双目运算符了吧。

#include<stdio.h>
int main()
{
	int a = 4;
	int c = 1.5;
	printf("%lf\n",a*c);
	return 0;
}

5.3/

运算符/是用来完成除法运算的,与前面不同的是,如果操作符的两端都是整数,但是实际结果为小数的话,那么计算机的运算结果还是为整数,会丢弃掉小数点小数部分。如果想要得到正确的结果,两个操作数必须要有一个是小数才行。

#include<stdio.h>
int main()
{
	printf("%d\n",6/4);//得到两个操作符都不是小数的结果
	printf("%f\n",6.0/4);//得到两个操作符其中有一个是小数的结果
	return 0;
}

给你们一个练手代码题:问:a的最终结果是多少

#include<stdio.h>
int main()
{
	int a = 5;
	a = (a/20)*100;
	printf("%d\n",a);
	return 0;
}

5.4%

%这个运算符用于求模运算,所谓求模运算就是求两个数的余数,所以这运算符仅限整数使用,小数不能使用,负数的求模规则是,结果的正负号由第一个运算数决定

#include<stdio.h>
int main()
{
	printf("%d\n",6%4);
	printf("%d\n",-6%4);
	printf("%d\n",6%-4);
	return 0;
}

6.赋值操作符:=和复合赋值

在创建变量时给变量一个值叫做初始化,但是当变量创建好后,在给变量一个值,这种行为就叫做赋值了。
赋值操作符:=是一个可以随时给变量赋值的操作符。

6.1连续赋值

赋值操作符可以连续赋值,但不推荐使用,因为不便于观察代码的运行细节。如;

#include<stdio,h>
int main()
{
	int a = 12;
	int b = 44;
	int c = 3;
	c = b= a;//连续赋值是从右向左依次赋值的
	printf("%d\n",c);
	return 0;
}

6.2复合赋值

在写代码时我们可能会对一个数进行自增、自减的操作,如下:

#include<sttdio.h>
int main()
{
	int a = 11;
	a +=2;//其实也就是a=a+2;
	printf("%d\n",a);
	return 0;
}

C语言还提供了其他复合赋值符,如:-=,*=,/=,%=,>>=,<<=,&=,|=,^=。

7.单目操作符:++、–、+、-

前面我们知道了什么是双目操作符,现在我们来学习什么是单目操作符,通过上面我们学习双目操作符的经验,单目操作符
其实就是只有一个操作数的操作符,++,–,+(正号),-(负号)就是单目操作符。

7.1++和–

++是一种自增操作符,分为前置++和后置++,–是一种自减操作符,也分为前置–和后置–。

7.1.1前置++

计算口诀,先加1,后使用

#include<stdio.h>
int main()
{
	int a = 2;
	int b = ++a;
	printf("%d\n",b);//计算口诀说先加1再使用,所以,先把++a给算了,得3,再把3赋值给b,所以b=3
	printf("%d\n",a);//++a是自己增加1,并且已经是先算过了,所以a=3
	return 0;
}

7.1.2后置++

计算口诀:先使用,再加一

#include<stdio.h>
int main()
{
	int a = 2;
	int b = a++;
	printf("%d\n",b);//先使用,也就是说a++先不计算,先把a的值赋值给b,然后再计算a++的值,也就是b = 2
	printf("%d\n",a);//上面说赋值后计算a++的值,所以啊经过自加后,a = 3
	return 0;
}

7.1.3前置–

如果你看懂了前面的前置++,那么这个前置–和前置++是一样的,只不过把+换成了-。
计算口诀:先减1,再使用

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

7.1.4后置–

和后置++一样,除了符号不同其他没啥不同
计算口诀:先使用,再–

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

7.2+和-

这里的+是正号,-是负号,都是单目操作符
运算符+对值的正负没啥影响,完全可以省略,但写了也不会报错。
int a = +10;等于 int a = 10;
运算符-可以改变一个值的正负,如果在正数前面加一个-,这个数会变成负数,如果在负数前加-,这个数会变成正数。

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

8.强制类型转换

在操作符中还有一种特殊的操作符,叫做强制类型转换,直接上代码:

#include<stdio.h>
int main()
{
	int a = (int)3.14//强制把3.14转换成整型,如果没有(int),编译器将会报错
	printf("%d\n",a):
	return 0;
}

强扭的瓜不甜,如果不是万不得已的情况下,我们是不会轻易使用强制类型转换的,如果不需要强制类型转换,自然更好。

9.scanf和printf介绍

9.1printf

9.1.1printf的基本用法

printf是将参数文本输出到屏幕。它名字里的f代表format(格式化),表示可以定制输出文本的格式,具体代码上一章有,我
就不过多赘述了。printf()不会在行尾自动添加换行符,执行完后光标会停留在输出结束的地方,所以我们可以在输出文本
的结尾添加一个换行符\n。

#include<stdio.h>
int main()
{
	printf("hehe\n");
	return 0;
}

printf是标准库的头文件stdio.h定义的,所以在使用前要在主函数前加上这个头文件。

9.1.2占位符

printf()可以输出文本中指定的占位符
占位符就是说这个位置可以被后面对应的值代替。

#include<stdio.h>
int main()
{
	int a = 2024;
	printf("今年是%d年\n",a);
	printf("%s is cool",zhangsan);
	return 0;
}

printf的占位符个数与参数个数息息相关,如果有n个占位符,则有n+1个参数。

9.1.3占位符的列举

%a
:⼗六进制浮点数,字⺟输出为⼩写。
• %A
:⼗六进制浮点数,字⺟输出为⼤写。
• %c
:字符。
• %d
:⼗进制整数。
• %e
:使⽤科学计数法的浮点数,指数部分的
e
为⼩写。
• %E
:使⽤科学计数法的浮点数,指数部分的
E
为⼤写。
• %i
:整数,基本等同于
%d

• %f
:⼩数(包含
float
类型和
double
类型)。
• %g
:6个有效数字的浮点数。整数部分⼀旦超过6位,就会⾃动转为科学计数法,指数部分的
e
为⼩写。
• %G
:等同于
%g
,唯⼀的区别是指数部分的
E
为⼤写。
• %hd
:⼗进制shortint类型。
• %ho
:⼋进制shortint类型。
• %hx
:⼗六进制shortint类型。
• %hu
:unsignedshortint类型。
• %ld
:⼗进制longint类型。
• %lo
:⼋进制longint类型。
• %lx
:⼗六进制longint类型。
• %lu
:unsignedlongint类型。
• %lld
:⼗进制longlongint类型。
• %llo
:⼋进制longlongint类型。
• %llx
:⼗六进制longlongint类型。
• %llu
:unsignedlonglongint类型。
• %Le
:科学计数法表⽰的longdouble类型浮点数。
• %Lf
:longdouble类型浮点数。
• %n
:已输出的字符串数量。该占位符本⾝不输出,只将值存储在指定变量之中。

%o
:⼋进制整数。
• %p
:指针。
• %s
:字符串。
• %u
:⽆符号整数(unsignedint)。
• %x
:⼗六进制整数。
• %zd

size_t
类型。
• %%
:输出⼀个百分号。

9.1.4限定宽度

printf()允许限定占位符的最小宽度,代码如下:

#include<stdio.h>
int main()
{
	printf("%5d\n",123);
	return 0;
}

这个限定宽度为5,也就是说最少要有5个数,如果不够从左边开始补空格,缺几个补几个,这个则是在123前面补两个空格
如果比5个多则什么都不动,毕竟这个限制的是你最小宽度,没管你最大宽度。

9.1.4.1总是显示正负号

默认情况下不会显示正负号,如果想要显示就在占位符前加上正负号就行了,因为printf打印的是双引号里面的数据。

#include<stdio.h>
int main()
{
	int a = 2;
	printf("+%d\n",a);
	printf("-%d\n",a);
	return 0;
}
9.1.4.2限定小数位数

输出小数时,如果没有限定小数位数,vs2022的编译器会自动输出小数点后6位小数,如果想要限制小数点后2位数,则可以写成%.2f

#include<stdio.h>
int main()
{
	dounle a = 3.14;
	printf("%.2f\n",a);
	return 0;
}

这种方式也可以和限定宽度相结合,并且这俩哥们也可以换成*,就像占位符一样可以通过后面的数而改变,现在我来演示一下

#include<stdio.h>
int main()
{
	dounle a = 3.14;
	printf("%6.2f\n",a);//限制这个小数最低输出6位,小数点后保留两位
	printf("%*.*f\n",6,2,a);//这俩*分别对应6,2  方便修改数据
	return 0;
}
9.1.4.3输出部分字符串

跟上面的限制小数点位数差不多,限制输出的字符串就是%.【m】s如:%.5s。

#include<stdio.h>
int main()
{
	printf("%.5s\n",hello word);
	return 0;
}

9.2scanf

有了输出那肯定就有输入,scanf就是一个给变量输入数值的库函数,跟printf一样,使用时需要先定义stdio.h头文件。

#include<stdio.h>
int main()
{
	int score = 0;
	printf("请输入成绩:");
	scanf("%d",&score);
	printf("您的成绩是:%d\n",score):
	return 0;
}

9.2.1基本用法

当程序执行到scanf是,会停下来等待用户输入,输入完后按下回车键,将其存入变量
scanf()和printf()语法极为相似。
不过在占位符后面,&score的意思是&是取地址符,读取地址用的,后面跟上变量名,表示读取这个变量的地址,方便把输入的数据存储进变量中
如果需要多组输入数据,如:

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

像这种多组输入,scanf()括号里双引号里写的啥,你就在键盘上输入啥,一个不能多,一个也不能少,如上面是两个%d则是要我们输入两个整数,我们在输入完一个整数后按空格,表示我们输入完一个整数,可以开始输入下一个整数了,输入完后按回车键,存入变量。注意:%d占位符会忽略起手的空格,也就是说如果占位符是%d,你一开始输入空格没有半毛钱作用。

9.2.2scanf的返回值

scanf的返回值是一个整数,返回值的多少取决于它读取变量成功的个数
如果没有读取任何项,或者匹配失败,则返回0。如果在成功读取任何数据之前,发⽣了读取错误或者遇到读取到⽂件结尾,则返回常量EOF。

#include <stdio.h>
 int main()
 {
 int a = 0;
 int 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;
 }

如果输入两个数后,按ctrl+z键,提前结束输入。
如果一次都不输入就提前结束输入,那么r = -1,也就是EOF。

9.2.3占位符

scanf的常用占位符如下,与printf的差不多。
• %c
:字符。
• %d
:整数。
• %f

float 类型浮点数。
• %lf

double 类型浮点数。
• %Lf

long double 类型浮点数。
• %s
:字符串。
• %[]
:在⽅括号中指定⼀组匹配的字符(⽐如%[0-9] ),遇到不在集合之中的字符,匹配将会停止。
除了%c以外都会自动忽略起首的空白字符%c不忽略空白字符,总是返回第一个字符,无论该字符是否为空格。
下⾯要特别说⼀下占位符%s,它其实不能简单地等同于字符串。它的规则是,从当前第⼀个⾮空⽩字符开始读起,直到遇到空⽩字符(即空格、换⾏符、制表符等)为⽌。
而限制数据类型长度则是%【m】s,没有·。

9.2.4赋值忽略符

就是在%后加一个*,就表示该占位符没有对应变量,不会返回值,解析后就被丢弃。如;

#include<stdio.h>
int main()
{
	int year = 0;
	int month = 0;
	int day = 0;
	scanf("%d%*s%d%*s%d",&year,&month,&day);//这样无论输入2024-3-26还是2024/3/26存入变量的值都一样了,因为,把空格,或者斜杠个忽略了。
	printf("%d %d %d\n",year,month,day);
	return 0;
}
  • 39
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值