常见的数据类型有整型类型、字符类型、浮点类型。
整型类型来描述整数,字符类型来描述字符,浮点类型来描述小数。
具体类型如下图
在程序定义一个整型可以使用int
int在内存中占4个字节
由于在内存中定义一个int可使用的空间有限
若数据较大内存无法存储过多
此时定义一个整型可以使用long int 或者 long long int
long int 占 4或8个字节(64位编译器即为8字节,32编译器即为4字节) long long int 占8个字节
本着不浪费空间的原则,一般定义int就够用了
若数据更小,如年龄最多只为3位数这类的,可以用short int定义,位2个字节(一个字节8个bit,若是无符号位则可存储8位二进制数,有符号位为7位二进制数,关于内存中符号位有更多内容,就不展开了)
int x; //4个字节
short int x;//2个字节
long int x;//4或8个字节
long long int x;//8个字节
程序定义一个字符型可以使用char
char在内存中占1个字节
char x;
在程序定义一个浮点型可以使用float
float在内存中占4个字节
double在内存中占8个字节
long double在内存中占12个字节
浮点型和整型类似(本着节省空间的原则看情况使用多大字节来定义)
float x;//4个字节
double x;//8个字节
long double x;//12个字节
在C99中也引入了布尔类型,来专门表示真or假
true表示真,falsse表示假
但是布尔类型的使用需要包含头文件
bool类型可以用在判断或者循环语句中作为条件
#include
int main()
{
_Bool x = true;
if (x) {
printf("helloworld");
}
}
sizeof是一个关键字,也是操作符,抓门用来计算sizeof的操作符数的类型长度的,单位是字节。
printf("%d",sizeof(int)) //输出即为4(int类型4个字节)
注:sizeof 中表达式不计算
#include
int main()
{
short a = 2;
int b = 10;
printf("%d\n",sizeof(a = b + 1));
printf("a = %d",a); //运行结果为 a = 2
return 0;
}
signed 关键字表示一个类型带有正负号,包含负值
unsigned 关键字表示该类型不带有正负号,只能表示零和正整数
这两个关键字是用来修饰字符型和整型的
对于整型(int)来说,默认是带有正负号的,也就是说 int 等同于 signed int
所以一般signed可以省略,当然加上也不会有错误
signed int x;
//等同于
int x;
用unsigned的好处是,同样长度的内存能够表示的最大整数值增大了一倍
例如:signed short int 为2个字节,也就是16个bit,第一个为符号位,则取值范围为(-32768~32767),而unsigned short int 的取值范围是:(0~65535),最大值增大了一倍
而在字符类型char中,C语言规定 char 类型默认是否带有正负号,是由当前系统决定的
所以 char 不一定等于 signed char ,也有可能等于 unsigned char
signed char a; //范围为 -128 ~ 127
unsigned char a; //范围为 0 ~ 255
C语言中把经常变化的值称为变量,不变的值称为常量
变量创建的语法形式如下
char name; //char 为数据类型,name为变量名
int age; //整型变量
char ch; //字符变量
double weight; //浮点型变量
如果给变量一个初始值,就叫初始化
int age = 10;
char ch = 'w';
double weight = 50.5;
全局变量:在大括号外部定义的变量就是全局变量
全局变量的使用范围更广,整个工程中想使用,都是有办法使用的
#include
int a = 10;
int main()
{
printf("a = %d",a); // 输出结果为 a = 10
return 0;
}
局部变量:在大括号内部定义的变量就是局部变量
局部变量的使用范围比较局限,只能在自己所在的局部范围内使用
#include
int main()
{
int a = 10;
printf("a = %d",a); // 输出结果为 a = 10
return 0;
}
如果有两个相同的变量名字a既在大括号外部定义也在内部定义会发生什么?
#include
int a = 10;
int main()
{
int a = 5;
printf("a = %d",a); // 输出结果为 a = 5
return 0;
}
如此看来局部变量的优先级是高于全局变量的
一般我们在学习C语言或者C++的时候都会关注内存里的三个区域:栈区、堆区、静态区
在写代码的时候,一定会涉及计算,为了方便计算,C语言提供了一种操作符,名叫算术操作符。分别有+ - * / %,这些操作符都是双目操作符
注:操作符也被叫做算术符
+和-都是用来完成加法和减法,加和减都是有两个操作数的,这种操作符也被叫做双目操作符
加法如下:
#include
int main()
{
int a = 5,b = 10,ret; //初始化
ret = a + b; //运算结果
printf("%d", ret); //打印结果ret = 15
return 0;
}
减法如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include
int main()
{
int a = 5,b = 10,ret;
ret = b - a; //减法运算
printf("%d", ret); //打印结果为 ret = 5
return 0;
}
运算符*是用来进行乘法运算,如:
#include
int main()
{
int num = 5;
printf("%d\n", num * num); // 输出 25
return 0;
}
运算符/是用来进行除法运算,如:
#include
int main()
{
float x = 6 / 4;
int y = 6 / 4;
printf("%f\n", x); // 输出 1.000000
printf("%d\n", y); // 输出 1
return 0;
}
至于为什么 6 / 4结果为1,是因为 6和4都为整型数据,除法运算之后得到的结果只能为整型数据,所以得到的计算他的商,x和y都被赋值6/4,故都为1,但x为float类型,所以会有小数点
再来看个例子:
#include
int main()
{
int score = 5;
score = (score / 20) * 100;
return 0;
}
如果你经过一通计算,可能会认为score的结果为25,但其实答案是0
因为score先除以20,再乘的0,在除以20的过程中,结果已经变成了0,所以0*100=0
运算符%是进行取余运算,该运算符只能用于2个整型数据,如:
#include
int main()
{
int x = 6 % 4; // x = 2
return 0;
}
负数的规则是结果的正负号由第一个运算数的正负号决定,例如:
#include
int main()
{
int a = -10 , b = 4 , ret;
ret = a % b;
printf("ret = %d\n", ret); //ret = -2
b = -4;
printf("ret = %d\n", ret); //ret = -2
return 0;
}
开头的a = -10决定了ret只能是负数
在变量创建时给予的值叫做初始化,而变量创建好后给予一个值叫做赋值
int a = 100;//初始化
a = 200;//赋值,这⾥使⽤的就是赋值操作符
赋值操作符=是一个可以随时可以给变量赋值的操作符
赋值操作符可以连续赋值,例如:
int a = 3;
int b = 4;
int c = 5;
c = b = a + 5;
上图最后一行的操作可以等同为
b = a + 5;
c = b;
但建议还是拆开来写,这样更方便自己和他人看代码
在写代码时,我们经常可能对一个数进行自增自减的操作,如下代码:
int a = 10;
a = a+3;
a = a-2;
在C语言中提供了 很多方便的操作符有:+= -= *= /= %= >>= <<= &= |= ^=,这些复合赋值符更加方便了我们编写代码
例如上述代码可用以下代码替换,效果相等
int a = 10;
a += 3;
a -= 2;
前面介绍的都是双目操作符,有两个操作数,现在所说的单目操作符,只要一个操作数,被称为单目操作符。
++和--是一种自增或自减的操作符,都分为前置++(--)、后置++(--)
int a = 10;
int b = ++a; //++a将a + 1,再将a+1赋值给b
printf("a = %d,b = %d",a,b); //输出结果为a = 11,b = 11
上述代码也可以理解为:
int a = 10;
a = a + 1;
int b = a;
printf("a = %d,b = %d",a,b);
计算口诀为:先加1,后使用
a原先为10,之后加了1变成11,11再赋值给b
int a = 10;
int b = a++; //先赋值给b,a再自增
printf("a = %d,b = %d",a,b); //输出结果为a = 11,b = 10
上述代码也可以理解为:
int a = 10;
int b = a;
a = a + 1;
printf("a = %d,b = %d");
计算口诀为:先使用,后加1
a原先为10,先使用赋值给了b,再加1
如果你听明白了前置++,那么前置--也类似,只是将+1变成-1
int a = 10;
int b = --a; //--a将a - 1,再将a-1赋值给b
printf("a = %d,b = %d",a,b); //输出结果为a = 9,b = 9
计算口诀:先使用,后减1
与后置++类似
int a = 10;
int b = a--; //先赋值给b,a再自减
printf("a = %d,b = %d",a,b); //输出结果为a = 9,b = 10
计算口诀:先减1,后使用
操作符中还有一种特殊的操作符是强制类型转换,形式如下:
int a = 3.14;
//a的是int类型, 3.14是double类型,两边的类型不⼀致,编译器会报警告
如果为了消除这种警告,我们可以强制类型转换
int a = (int)3.14;
//意思是将3.14强制类型转换为int类型,这种强制类型转换只取整数部分
强扭的瓜不甜,如果不需要强制类型转换就能实现代码,就尽量不要使用
printf的作用是将参数的文本输出到屏幕上,print表示打印,f是format(格式化),表示可以定制输出文本格式
#include
int main()
{
printf("Hello world\n");
return 0;
}
上面的代码会将Hello world输出到屏幕上
printf不会在行尾自动添加换行符,光标就停留在末尾
若想换行输出新内容,可以使用\n添加这个换行符
#include
int main(void)
{
printf("Hello\nWorld\n"); //输出为Hello
return 0; // World
}
printf()是在标准库的头文件stdio.h定义的。使用这个函数之前必须加上这个头文件
在前面的代码中
%d即为占位符占位符的第一个字符必须为%,第二个字符表示占位符的类型,%d表示里面填入的是一个整数
输出文本里面可以使用多个占位符,上面的代码就是使用了两个,并传递了两个变量,他们是一一对应的关系,如果不给东西给占位符,那么很可能会输出一个随机值
printf()可以定制占位符的输出格式
#include
int main()
{
printf("%5d\n", 123); // 输出为 " 123"
return 0;
}
%5d表示这个占位符的宽度至少为5位,所以上面只有123的话不够5位,会自动添加两个空格补齐,默认是右对齐,如果希望是左对齐,可以加个-,如下:
#include
int main()
{
printf("%-5d\n", 123); // 输出为 "123 "
return 0;
}
当然也可以对%f使用,如:
#include
int main()
{
printf("%12f\n", 123.45); // 输出 " 123.450000"
return 0;
}
一共也是十二位,小数点后默认6位,再向前补齐两位,所以自动添加了两个空格
默认情况下,printf()不会有正号在前面,只会显示负号,我们可以这么做
#include
int main()
{
printf("%+d\n", 12); // 输出 +12
printf("%+d\n", -12); // 输出 -12
return 0;
}
输出小数时,会默认输出小数点后六位,如果只希望有两位的话,可以这么做:
#include
int main()
{
printf("Number is %.2f\n", 0.5); //输出Number为0.50
return 0;
}
如果想保留三位的话,可以改成%.3f
所以还能这么做:
#include
int main()
{
printf("%6.2f\n", 0.5); // 输出为 " 0.50"
return 0;
}
%6.2f的6将最小宽度定为6,2是保留两位小数,所以输出0.50的时候会在前面加上两个空格,(.)也算一位
当然以上最小宽度和小数位数这两个限定值,都可以用*代替,通过printf()的参数传入,如:
#include
int main()
{
printf("%*.*f\n", 6, 2, 0.5);
return 0;
}
// 等同于printf("%6.2f\n", 0.5);
%s用来表示输出字符串,默认是全部输出。如果只想输出指定长度,可以用 %.[m]s 指定输出的长度,其中[m]代表一个数字,表示所要输出的长度,如下:
#include
int main()
{
printf("%.5s\n", "hello world"); //只输出了hello
return 0;
}
上面的 %.5s 表示只要5个字符,即为hello
当我们定义了一个变量,如果我们需要给变量输入值就可以使用 scanf()函数,如果要打印在屏幕上就用printf()函数,如下:
#include
int main()
{
int score = 0;
printf("请输⼊成绩:");
scanf("%d", &score);
printf("成绩是:%d\n", score);
return 0;
}
运行结果为
下面来介绍scanf()函数
scanf()用于读取用户的键盘输入
当程序运行到了scanf()函数的时候就会停止运行,等待用户输入,当用户输入完毕就带着用户赋给变量的值继续运行,使用scanf()函数时也要注意和printf()函数一样,都需要包含头文件stdio.h
scanf()的语法与printf()类似
scanf("%d", &i);
但要注意的是一般的变量前面都要加入&这个取地址符号,不一般的情况就是变量本身就是地址,例如数组、指针这些赋值时可以不用&
在用户输入数值时,会自动过滤空白符号,包括空格、制表符、换行符等
所以用户输入时,有多个空格和换行并不影响scanf()函数解读
解读用户输入时,如果上次的scanf()函数输入的值过多,则这次会从上一次遗漏的第一个字符开始,直到读完缓存,或者遇到不符合条件的字符为止
#include
int main()
{
int x;
float y;
// ⽤⼾输⼊ " -13.45e12# 0"
scanf("%d", &x);
printf("%d\n", x);
scanf("%f", &y);
printf("%f\n", y);
return 0;
}
上述代码中,第一个scanf()函数只会解读到-13,然后碰到.就结束,因为它并不属于有效字符,然后下一个scanf()就会开始读取.45e12 (e12表示的是12次方),到#不属于有效字符就停止了,以下是结果
前面的-13理所当然
而后面的一长串其实应该是0.45 * 10 ^ 12,但内存中数据有时候无法精确保存,所以算出来的值是近似相等而不是绝对相等。所以0.45 * 10 ^ 12进去后保存的就是最后那一行的数字
scanf函数返回的是一个整数,表示成功读取的变量个数。
如果没有读取到任何项或者保存失败,则返回0,如果在读取成功之前发生了读取错误或者遇到读取到该文件末尾,则返回常量EOF
#include
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=2
如果直接按 ctrl + z
则返回值为EOF也就是-1
有时用户的输入可能不符合scanf的格式
#include
int main()
{
int year = 0;
int month = 0;
int day = 0;
scanf("%d-%d-%d", &year, &month, &day);
printf("%d %d %d\n", year, month, day);
return 0;
}
上面示例中,如果用户输入2023-11-24就可以正常读入,但万一用户是输入2023/11/24呢?
为了避免这种情况,scanf函数提供了一种赋值忽略符,只要把*加在任意的占位符的百分号后面,该占位符就不会返回值,解析后将被丢弃
#include
int main()
{
int year = 0;
int month = 0;
int day = 0;
scanf("%d%*c%d%*c%d", &year, &month, &day);
return 0;
}
这样就可以成功避免格式不对而导致的错误了
希望此文章对您有帮助