C语言——变量、操作符(赋值+算术+强制类型转换)

📝学习预警:
下面文章我们将学习变量(变量的创建、命名、初始化、分类),操作符(赋值操作符、算术操作符(单目和双目)、强制类型转换),

  • 算术操作符在printf中
    • 1、对一个变量进行一次读取和修改
    • 2、对一变量多次读取和修改,
  • 强制类型转换中还拓展了隐式类型转换,并粗略讲解了字符型和整型的线性运算、并且整型和字符型可以相互转换

1️⃣变量

1.1、变量的创建

❓在数据类型的那篇文章中我们已经学习了数据类型,那么这些类型有什么用呢?

  • 类型是为了创建变量

变量创建语法:数据类型+变量名
data_type name

1.1.1、变量的命名规则

  • 只能由字母(大小写均可)、数字、下划线-组成
  • 长度不可超过63个字符
  • 不可以用数字开头
  • 不能使用关键字
  • 变量名是区分大小写的
int a_11;
int a_;
int _11;
int _2b;
以上写法均可
int a;//整型变量
char c;//字符变量
double d;//浮点型变量
······
***************
但不可以:
int char;
int 12h;
int 12_;

1.1.2、变量初始化

在变量的创建时就给一个初始值,就叫初始化

int age=10;
char ch = 'w';
double weight = 50.8;

❗️注意:
float a = 10.3;//10.3在编译器是认为double类型
double c = 10;
float d = 18.4f;//在小数后面加个 f 才可以被认为是float类型

1.1.3、变量的分类(局部/全局)

  • 全局变量:在大括号外面(main函数外)定义的变量就是全局变量
    • 使用的范围更广,在整个项目中想使用都可以使用到
  • 局部变量在大括号内部定义的变量就是局部变量
    • 使用的范围局限,只能在自己所在的范围内使用
  • ❗️当局部变量和全局变量的变量名时, 局部变量的优先级高于全局变量
  • 可以理解成大括号内就是自己的家,括号外是社会
  • 局部变量好比是自己家里的电动车
  • 全局变量好比共享电动车车
  • 自家有车还开什么共享的车
#include<stdio.h>
int a = 10;//全局变量
int main()
{
	//int a = 100;//局部变量
	int b = 10;//局部变量
	int c = 0;
	c = a + b;
	//当局部变量a没有被注释掉,就是100+10=110(a+b)
	//变量名同,局部变量优先级高
	//当局部变量被注释掉了,就是10+10=20(a+b)
	printf("c = %d\n", c);
	return 0;
}
📌局部变量和全局变量在内存的存储位置
  • 变量创建的本质是:在内存中申请一块空间

我们在学习C语言时,会关注内存的三个区域:栈区、堆区、静态区

  • 局部变量放在内存的栈区
  • 全局变量放在内存的静态区
  • 堆区是用来动态内存管理的
内存:8,16,32G
栈区:局部变量和函数参数
堆区:动态内存管理 malloc,calloc,realloc,free
静态区:全局变量和静态变量

2️⃣赋值操作符:=

在变量创建的时候给一个初始值是初始化;而变量创建好后,再给一个值,是赋值

int a =10;//初始化
a = 90;//赋值

int b;//未初始化
b = 20;//赋值

🤔我们为什么要初始化呢?

  • 在未初始化时,局部变量的值时随机值;而全局变量的值是0

在这里插入图片描述

在尝试时,在vs2022会报错,可以使用vscode来运行,但我试了发现全局和局部结果都是0,全局一定是0;局部一定是随机数

  • 赋值操作符=是一个可以随时给变量赋值的操作符

2.1、连续赋值

#include<stdio.h>
int main( )
{
    int a = 3;
    int b = 4;
    int c ;  
    c = b = a + 3; // 连续赋值,从右到左依次赋值
    printf("%d", c);
    return 0;
}

不建议连续赋值,因为这样对代码的解读能力差,建议拆开来写,这样方便观察代码,如下:

#include<stdio.h>
int main()
{
    int a = 3;
    int b = 4;
    int c;
    b = a + 3;
    c = b; 
    printf("%d", c);
    return 0;
}

2.2、复合赋值符

我们在写代码时会对一个数进行加减乘除,如下:

int a = 10;
a = a + 3;
···

我们可以使用简便的写法,如下:

int a = 10;
a += 3;//相当于a= a+3
a -= 3;//a =a-3
a *= 3;//a = a*3
a /= 3;//a =a/3
a %= 3;//a =a%3
···
  • 复合赋值符有:
    • +=-=*=/=%=
    • >><<=&=|=^=

3️⃣算术操作符

  • 操作符 = 运算符(只是翻译不同罢了)

3.1、双目操作符:+-*/%

可以理解成双目操作符是有两个操作数的,位于操作符两端的就是它们的操作数

3.1.1、+加 和 -

  • 加法和减法
#include<stdio.h>
int main()
{
	int a = 100;
	int b = 10 - 5;//-
	int c = 0;
	c = a + b;//+
	printf("c = %d\n", c);
	//105
	printf("c = %d\n", a + b);//+
	//105
	return 0;
}

3.1.2、*

  • 乘法
#include<stdio.h>
int main()
{
	int a = 10;
	int b = 2 * 5;//*
	int c = 0;
	c = a + b;//+
	printf("c = %d\n", c);
	//20
	printf("c = %d\n", a * b);//*
	//100
	return 0;
}

3.1.3、/

  • 除法
  • 除号两端是整数,就是整数除法,最终结果也是整数
#include<stdio.h>
int main()
{
	//因为9和5都是整型,相除后还是整型,取整数(不用四舍五入,直接取整数)
	//取得整数1后,因为a是浮点型,输出1.000000
	float a = 9 / 5;
	printf("a = %f\n", a);

	//因为6和4都是整型,相除后还是整型,取整数(不用四舍五入,直接取整数)
	//取得整数1,输出1
	int b = 6 / 4;
	printf("b =%d\n", b);

	//占位符不要乱用,因为a是浮点型,不应该用%d,下面的b的道理相同
	//下面两个都是错误的写法,不要学习
	printf("a = %d\n", a);
	printf("b =%f\n", b);

	return 0;
}

如果希望得到浮点数,那么必须在两个操作数中至少有一个是浮点数,这样才可以进行浮点数除法

#include<stdio.h>
int main()
{
	//注意5.0是double类型,如果改成5.0f就是float类型
	//因为9是整型,5.0是浮点型,相除后就变成浮点型
	//因为a是浮点型,输出1.800000
	float a = 9 / 5.0;//或者是9.0/5,或者是9.0/5.0
	printf("a = %f\n", a);
	
	//下面的写法相当于是将double[9 / 5.0]类型转换成int[b]类型(这个是自动转换的),可能存在数据丢失的情况
	//因为将8字节的数据放进4字节的空间里
	//不建议这么写
	int b = 9 / 5.0;
	printf("b = %d\n", b);

	return 0;
}

3.1.4、%取余数

  • 取余:返回两个整数相除的余数
  • 这个操作符只能用于整数之间,不可以浮点数
  • 负数取余的规则:结果的正负号由第一个运算数决定只要第一个运算数是负数结果就是负数
#include<stdio.h>
int main()
{
	int a = -5;
	int b = -2;
	int c;
	c = a % b;
	printf("%d", c);//-1
	return 0;
}

3.2、单目操作符:++--+-

在C语言中有一些操作符时只有一个操作数,则该操作符被称为单目操作符

3.2.1、++自增前置和后置

++是一个自增的操作符,分别由前置和后置自增;

💥3.2.1.1、++前置
int a = 10;
int b = ++a;
printf("a = %d\nb = %d\n",a,b);
******************************
输出结果:
a = 11
b = 11

先+1(自增),后使用
上面的代码相当于下面的:

int a = 10;

//a 先 +1(自增),变成 11
a = a + 1;		//11

//后使用,将a 的值赋给 b
int b = a;		//11
printf("a = %d\nb = %d\n", a, b);
💥3.2.1.2、++后置
int a = 10;
int b = a++;
printf("a = %d\nb = %d\n",a,b);
******************************
输出结果:
a = 11
b = 10

先使用,后+1(自增)
上面的代码相当于下面的:

int a = 10;
//先使用,将a 的值赋给 b
int b = a;	//10

//后面 a 要 +1(自增),变成 11
a = a + 1;		//11		
printf("a = %d\nb = %d\n", a, b);
📌附1:在printf中如果作为打印的参数会如何?
  • 有些时候刷题或者考试时会看到printf的函数中使用了自增(或自减)
  • 后续自减就不讲这个了,原理是一样的
  • 比如:printf("a = %d\n", a++);

底层逻辑:
这些语句打印的就是变量a每一步变化后的值。每执行一次a++或++a,a的值都会发生变化,打印出来的就是变化后的结果。

  • 具体来说:
  • a++:打印的是自增前的a,打印后a加1。
  • ++a:先让a加1,再打印自增后的a。

可以简记成:打印的是 a++ / ++a 的值

从下面的代码中可以看出其在printf中自增变化的:

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

	//首先a == 1
	//其次a++,a自增变成-->a == 2;a++ == 1
	//因为打印a++,所以输出结果为 1
	printf("a = %d\n", a++);	//1

	//首先a == 2
	//其次++a,a自增变成-->a == 3;++a == 3
	//因为打印++a,所以输出结果为 3
	printf("a = %d\n", ++a);	//3
	return 0;
}
📌附2:在printf中如果有多个作为打印的参数会如何?(只作为拓展)

这个只是拓展,但非常不建议这么写,要写也是分开写,

  • 语法上,这样写是合法的,编译不会报错。
  • 但这样写不推荐,因为你在一个表达式(printf参数列表)中多次对同一个变量a进行自增(a++、++a)[或自减)],这会导致未定义行为
  • C语言标准规定:如果在一个表达式中对同一个变量既有多次修改又有读取,结果是不可预期的。
  • 为什么最终结果是这样呢❓
    • a++:先用a当前的值,后自增。
    • ++a:先自增,后用a的新值。
  • 但在同一个printf参数列表里,编译器对参数求值的顺序没有规定,所以每次运行的结果可能不同,不同编译器、不同优化设置下结果也可能不同
#include<stdio.h>
int main()
{
	int a = 0;
	printf("a = %d\na++ = %d\n++a = %d\na++ = %d\na++ = %d\n++a = %d\n", a, a++ ,++a,a++, a++, ++a);	
	/*运行结果
		a = 5
		a++ = 4
		++a = 5
		a++ = 2
		a++ = 1
		++a = 5
	*/
	return 0;
}
📌附3:多次对某一变量的修改和读取(本质和“附2”一样)

这个只作为例子,不讲解,本质和附2一致
不建议这么写

#include<stdio.h>
int main()
{
	int a = 1;
	int r = (a++) + (a++) +(++a);
	printf("%d",r);
	return 0;
}
*******************************
在vs2022中输出结果为:6
在vscode章输出结果为:7

3.2.2、--自减前置和后置

--是一个自增的操作符,分别由前置和后置自增;

💥3.2.1.1、--前置
int a = 10;
int b = --a;
printf("a = %d\nb = %d\n",a,b);
******************************
输出结果:
a = 9
b = 9

先-1(自减),后使用
上面的代码相当于下面的:

int a = 10;

//a 先 -1(自减),变成 9
a = a - 1;		//9

//后使用,将a 的值赋给 b
int b = a;		//9
printf("a = %d\nb = %d\n", a, b);
💥3.2.1.2、--后置
int a = 10;
int b = a--;
printf("a = %d\nb = %d\n",a,b);
******************************
输出结果:
a = 9
b = 10

先使用,后-1(自减)
上面的代码相当于下面的:

int a = 10;
//先使用,将a 的值赋给 b
int b = a;	//10

//后面 a 要 -1(自减),变成 9
a = a - 1;		//9	
printf("a = %d\nb = %d\n", a, b);

3.2.3、+正号和-负号

  • 运算符+对一个数没有什么影响,是一个可以忽略的运算符,但是写了也不错
  • 运算符-是改变一个数的正负号
    例如:
    在这里插入图片描述

3.3强制类型转换

强制类型转换在大多数编程语言(如 C、C++、Java 等)中被视为一种操作符,强制类型转换是一种 显式的一元操作符,用于主动改变数据的类型,并遵循操作符的优先级规则。
语法:(type_name) expression

int a = 3.24;
//a是int类型,然而3.24是double类型,类型不一致,会警告丢失数据
*******************
*******************
要消除这个警告,我们就需要强制转换类型了
int a = (int)3.24;
//将3.24强制转换为int类型(只取整数部分,不会四舍五入)
#include <stdio.h>
int main()
{
	int a = 17;
	int b = 5;
	double c;
	
	//如果是下面的形式,输出的c = 3.000000;先是整数除法,只取整数部分,后面再转换为浮点型
	c = a / b;
	printf("c= %f\n", c);

	//下面是强制类型转换,输出的c = 3.400000
	c = (double)a / b;

	printf("c= %f\n", c);
	return 0;
}

📌附:隐式类型转换(整型提升)(拓展)

  • 当字符型与整型进行运算时,编译器会自动将字符隐式转换为整数(称为 整型提升

例如:
为什么下面的代码字符和整型可以线性运算,并且sum明明是整型却可以输出字符型呢❓(无报错,无警告)

#include <stdio.h>
int main() 
{
	int i = 17;
	char c = 'c'; // ASCII 值是 99
	int sum;
	sum = i + c;
	printf(" sum : %d\t%c\n", sum,sum);// 输出116		t
	return 0;
}

因为:在编程语言中,字符型(char)和整型(int)变量可以进行线性运算,是因为字符(ASCII码)在底层实际上是以整数的形式存储的。

为什么允许这种操作?

  • 历史原因:C 语言早期设计中将字符视为整数,这种特性被后续语言继承(如 C++、Java 等)。
  • 灵活性:字符的整数表示允许直接操作字符的编码。例如:
    • 大小写转换:'A' + 32 得到 'a'(因为 65 + 32 = 97)。
    • 字符偏移:'0' + 5 得到 '5'(因为 48 + 5 = 53)。

✒️作者小结:
以上教学了变量、赋值操作符、算术操作符的使用

  • 如果哪里有错误或不完整,欢迎大家指出来,我会积极进行修改
  • 谢谢大家的阅读🌹🌹🌹
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值