常量·变量·运算符

常量·变量·运算符

一、常量

1.1 字符串常量

字符串常量需要用 双引号 “” 引起来

“hqyj” “www.baidu.com” “1234”

每个字符串常量结尾都会有一个隐藏的字符 ‘\0’ 用来标识字符串结束的

也就是说 “hello” 字符串实际要占用6个字节的内存空间

注意下面几个用法

a 变量a

‘a’ 字符a

“a” 字符串a

将数据按照字符串方式输出,使用的占位符是 %s

#include <stdio.h>

int main(int argc, const char *argv[])
{
	//可以将字符串直接输出
	printf("hello\n");
	printf("%s\n", "hello");

	//也可以将字符串保存在字符数组中
	char str[32] = "www.hqyj.com";//--数组的用法 后面讲
	printf("str = [%s]\n", str);

	//也可以定义一个指针直接指向字符串常量
	char *p = "beijing"; //--指针的用法 后面讲
	printf("p = %s\n", p);
 
    //C语言中对字符串的处理 遇到 '\0' 就结束了
	char *p2 = "bei\0jing";
	printf("p2 = %s\n", p2);//bei

	return 0;
}

1.2 标识常量 --宏定义

宏定义就是给常量表达式起一个别名,使用这个名字,就相当于使用这个常量表达式,

如果常量表达式修改了,程序中所有使用这个名字的地方都会发生改变。

这个名字是一个标识符,要符合标识符的命名规范,宏定义的名字一般都是大写的。

格式:

#define  宏名  宏值

例:

#include <stdio.h>

#define STUDENT 30  //当宏值发生变化时,所有使用宏名的地方都会变化

int main(int argc, const char *argv[])
{
	printf("当前班级已有人数 %d\n", STUDENT);
	printf("当前班级已有人数 %d\n", STUDENT);
	printf("当前班级已有人数 %d\n", STUDENT);

	return 0;
}

注意事项:

1.宏定义是在预处理阶段完成替换的;

2.宏定义只是一个简单的替换、是无脑替换;

#include <stdio.h>

#define M 10
#define N 20
#define SUM1 M+N
#define SUM2 (M+N)

int main(int argc, const char *argv[])
{
	int ret = SUM1*4;
	//int ret = M+N*4;
	//int ret = 10+20*4;
	printf("%d\n", ret);//90

	int ret2 = SUM2*4;
	//int ret2 = (M+N)*4;
	//int ret2 = (10+20)*4;
	printf("%d\n", ret2);//120

	return 0;
}

二、变量

2.1 概念

在程序运行的过程中,值允许发生改变的量。

变量的大小:取决于定义变量的类型

变量的名字:是一个标识符,要符合标识符命名规范

定义变量的格式:

​ 存储类型 数据类型 变量名;

存储类型  数据类型  变量名;

存储类型:

const static extern register volatile auto ----C高级课程再讲

局部变量不写存储类型默认的都是 auto

2.2 变量的初始化和赋值

#include <stdio.h>

int main(int argc, const char *argv[])
{
	//初始化:在定义变量的同时,给变量赋一个初值
	int v1 = 1314;
	printf("v1 = %d\n", v1);//1314

	//如果定义变量没有初始化 里面就都是随机值
	int v2;
	printf("v2 = %d\n", v2);//不确定的值

	//如果定义变量不知道用谁初始化 可以使用0来初始化
	//v3 = 520;//错误的 变量需要先定义 才能使用
	int v3 = 0;
	printf("v3 = %d\n", v3);//0

	//变量是可以被重新赋值的
	v3 = 520;	// = 赋值运算符  将右边的值赋值给左边
	printf("v3 = %d\n", v3);//520
	v3 = v1;	//也可以使用变量给变量赋值
	printf("v3 = %d\n", v3);//1314

	//变量之间可以做运算
	v2 = v1+v3;
	printf("v1 = %d  v2 = %d  v3 = %d\n", v1, v2, v3);//1314 2628 1314
	
	//一行中可以定义多个变量 用逗号分隔
	int v4,v5,v6;

	//同一个作用域(同一个{})内 不允许定义重名的变量
	//int v4; //错误的 重名了

	return 0;
}

2.3 强制类型转换

在某次运算中,通过某种方式将变量的类型转换成其他类型来参与本次运算。

变量本身的类型不会改变,只是在本次运算中使用其他类型参与运算了。

强制类型转换简称 强转

注意:强制类型转换是不安全的,要谨慎使用

小的类型转大的类型一般没问题

但是大的类型转小的类型就可能会出现数据的截断和丢失

2.3.1 显式强转

格式:

(新的类型)变量名;
#include <stdio.h>

int main(int argc, const char *argv[])
{
	int m = 5;
	int n = 2;
	float ret1 = m/n;	//这种写法 因为 m 和 n本身是 int类型 所以运算的结果也是int类型
						//m/n 得到的结果就是 2  相当于把2赋值给 ret1
	printf("ret1 = %f\n", ret1);//2.000000
	
	//将 m 和 n 的类型转换成 float 来参与本次运算  得到的结果就是 float 类型的
	//相当于 把 2.500000 赋值给 ret2
	float ret2 = (float)m/(float)n;
	printf("ret2 = %f\n", ret2);//2.500000

	//m和n的类型不会改变
	printf("m = %d  n = %d\n", m, n);//5  2

	return 0;
}

2.3.2 隐式强转

隐式强转是编译器根据上下文自动推导的,

如果编译器觉得本次转换是安全的,则正常执行

如果编译器觉得是有风险的,一般会报一个警告,具体报不报取决于编译器的严谨程度。

#include <stdio.h>

int main(int argc, const char *argv[])
{
	float f = 3.1415;
	int m = f;	//这种操作是 取整 的操作  会舍弃小数部分
	printf("f = %f  m = %d\n", f, m);//3.141500  3

	return 0;
}

注意:

有符号数和无符号数参与运算时,会将有符号数转换成无符号数参与运算。

#include <stdio.h>

int main(int argc, const char *argv[])
{
	signed int a = -20;
	unsigned int b = 10;
	
	if(a+b > 0){
		printf("yes\n");//输出的是 
	}else{
		printf("no\n");
	}

	//不要尝试保存 a+b 的结果 
	//因为如果使用 signed int 保存 相当于把结果隐式强转成 有符号了
	//如果使用 unsigned int 保存 虽然结果是无符号的 
	//但是就没法说明 是在运算的过程中 将有符号数转换成 无符号数了
	
	//实际开发过程中不会出现这种场景

	return 0;
}

三、运算符

3.1 概念

运算符就是一个符号,是用来多个值之间进行运算的。

运算符可以连接多个表达式。

所谓的表达式就是由 运算符 运算量 标点符号 等组成的一个有效序列,

是用来说明一个运算过程的。

3.2 运算符的分类

算数运算符: + - * / %(模除,就是取余数的意思)

自增自减运算符:++ –

关系运算符: > < >= <= != == (判断相等要用两个等号)

逻辑运算符: && || !

位运算符: & | ^ ~ << >>

条件运算符(三目运算符): ?:

赋值运算符:= += -= *= … (复合赋值运算符)

sizeof运算符

逗号运算符: (,) ----不常用

3.3 算数运算符

+ - * / %(模除,就是取余数的意思)

注意:模除要求左右操作数必须是整数

想输出% 需要敲两个%

#include <stdio.h>

int main(int argc, const char *argv[])
{
	int m = 10;
	int n = 3;
	printf("m + n = %d\n", m + n);
	printf("m - n = %d\n", m - n);
	printf("m * n = %d\n", m * n);
	printf("m / n = %lf\n", (double)m / (double)n);//整型做除法 需要强转
	printf("m %% n = %d\n", m % n);				//想输出% 需要敲两个%

	double a = 5.28;
	double b = 3.14;
	printf("a + b = %lf\n", a + b);
	printf("a - b = %lf\n", a - b);
	printf("a * b = %lf\n", a * b);
	printf("a / b = %lf\n", a / b);
	//printf("a %% b = %lf\n", a % b);//% 要求左右操作数必须是 整数

	return 0;
}

C语言中输入的函数, scanf

#include <stdio.h>

int main(int argc, const char *argv[])
{
	int value = 0;
	printf("请输入一个整数 : ");
	//阻塞等待用户输入
	scanf("%d", &value); 	// & 取地址符
	printf("你输入的数据是 : %d\n", value);

	return 0;
}

练习:

从终端输入1个三位数 [100,999]

输出 个位+十位+百位 求和的结果,

如:输入:135

则输出:1 + 3 + 5 = 9

#include <stdio.h>
int main(){
    int num = 0;
    printf("请输入一个三位数:");
    scanf("%d", &num);
    
    int g = num % 10;//个位
    int s = num % 100 / 10;//十位
    int b = num / 100;//百位
    
    printf("%d + %d + %d = %d\n", b, s, g, b+s+g);
    
    return 0;
}

3.4 自增自减运算符

++ –

a++ <==> a = a+1

++a <==> a = a+1

a-- <==> a = a-1

–a <==> a = a-1

注意:以自增运算符为例 前加加和后加加 变量的值都加了1 但是表达式的结果是不一样的。

a = 10;

b = ++a;

上述两行之后,a = 11, b = 11

a = 10;

b = a++;

上述两行之后,a = 11, b = 10

#include <stdio.h>

int main(int argc, const char *argv[])
{
	int a = 10;
	int b = ++a;//相当于在此表达式之前完成a+1
	printf("a = %d  b = %d\n", a, b);//11 11

	int m = 10;
	int n = m++;//相当于在此表达式之后完成a+1
	printf("m = %d  n = %d\n", m, n);//11 10

	return 0;
}

++a和a++的区别:

虽然++a和a++等价的结果一样,但是运算过程不同,a++ 是先使用a的值,然后再对a做加1处理,++a是先对a作加1处理,然后再使用a的值。

3.5 关系运算符

> < >= <= != ==

关系运算符一般是用于比较大小关系的

关系运算符表达式的结果是一个 bool 类型,bool类型只有两种值 0 假 非0 真

一般多用于控制语句中

注意:

= 和 == 的区别

= 赋值运算符

== 关系运算符 判断是否相等的

//if else 语句说明
if(表达式){
    代码块1;
}else{
    代码块2;
}
//执行逻辑,如果表达式为真 则执行 代码块1 否则执行代码块2

例:

#include <stdio.h>

int main(int argc, const char *argv[])
{
	int a = 0;
	int b = 0;
	scanf("%d%d", &a, &b);//scanf可以连续输入多个数 输入时以空格或回车区别

	//其他关系运算符 用法同理
	if(a > b){
		printf("a>b\n");
	}else{
		printf("a<=b\n");
	}

	if(a == b){
		printf("yes\n");
	}else{
		printf("no\n");
	}

	return 0;
}

3.6 逻辑运算符

逻辑运算符是用来连接多个由关系运算符组成的表达式的。

逻辑运算符的结果 也是一个 bool 类型。

&& 逻辑与 表示并且的意思

逻辑与连接的多个表达式,如果都为真,整个表达式的结果才为真

有一个表达式结果为假,整个表达式的结果就为假

|| 逻辑或 表示或者的意思

逻辑或连接的多个表达式,有一个为真,整个表达式的结果就为真

如果所有表达式都为假,整个表达式才为假

! 逻辑非 表示逻辑取反的意思

真变假 假变真

例:

#include <stdio.h>

int main(int argc, const char *argv[])
{
	int a = 0;
	int b = 0;
	scanf("%d%d", &a, &b);

#if 0
	//逻辑与
	if(a >= 0 && b >= 0){
		printf("yes\n");
	}else{
		printf("no\n");
	}
#endif

#if 0
	//逻辑或
	if(a >= 0 || b >= 0){
		printf("yes\n");
	}else{
		printf("no\n");
	}
#endif

	//逻辑非
	if( !(a>b) ){
		printf("yes\n");
	}else{
		printf("no\n");
	}

	return 0;
}

逻辑运算符的短路原则

逻辑与的短路原则:

逻辑与连接的多个表达式,如果遇到某个表达式为假了,

足以判断整个表达式为假,后面的表达式就都不执行了

逻辑或的短路原则:

逻辑或连接的多个表达式,如果遇到某个表达式为真了,

足以判断整个表达式为真,后面的表达式就都不执行了

#include <stdio.h>

int main(int argc, const char *argv[])
{
	int a = 10;
	int b = 20;
	int c = 30;
	int ret = 0;

	ret = (a>0 && b<0 && ++c);//因为b<0为假 所以++c 不执行
	printf("ret = %d  a = %d  b = %d  c = %d\n", ret, a, b, c);//0 10 20 30

	a = 10;
	b = 20;
	c = 30;
	ret = 0;
	ret = (a<0 || ++b || ++c);//a<0为假 则执行++b  ++b为真 所以不执行 ++c
	printf("ret = %d  a = %d  b = %d  c = %d\n", ret, a, b, c);//1 10 21 30

	return 0;
}

3.7 位运算符

**位运算是针对二进制而言的,**位指的是bit位,但凡涉及位运算,

不管几进制的数据计算机中都会转换成二进制参与运算。

一般情况下涉及位运算使用的都是 无符号 数

如果是有符号数 可能需要考虑 原码、反码、补码转换的问题

位运算一般多用于硬件设备的控制或者标志位的控制。

& 按位与 按位运算 全1为1 有0为0

| 按位或 按位运算 有1为1 全0为0

^ 按位异或 按位运算 不同为1 相同为0
按位取反 按位运算 0变1 1变0

<< 按位左移 整个数据向左移动 低位补0 舍弃高位

>> 按位右移 整个数据向右移动 高位补0 舍弃低位

例:

#include <stdio.h>

int main(int argc, const char *argv[])
{
	unsigned char a = 0xa5;
	unsigned char b = 0x97;
	unsigned char c = 0;

	//按位与
	c = a & b;
	//a: 10100101
	//b: 10010111
	// &
	//c: 10000101 -->0x85
	printf("a & b = %#x\n", c);//0x85

	//按位或
	c = a | b;
	//a: 10100101
	//b: 10010111
	// |
	//c: 10110111 -->0xB7
	printf("a | b = %#x\n", c);//0xB7

	//按位异或
	c = a ^ b;
	//a: 10100101
	//b: 10010111
	// ^
	//c: 00110010 -->0x32
	printf("a ^ b = %#x\n", c);//0x32

	//按位取反
	c = ~a;
	//a: 10100101
	// ~
	//c: 01011010 -->0x5A
	printf("~a = %#x\n", c);//0x5A

	//按位左移
	c = a<<2;
	//a: 10100101
	// <<2
	//c: 10010100 -->0x94
	printf("a<<2 = %#x\n", c);//0x94

	//按位右移
	c = a>>2;
	//a: 10100101
	// >>2
	//c: 00101001 -->0x29
	printf("a>>2 = %#x\n", c);//0x29

	return 0;
}

小技巧:

1或任何数 结果都是1

1与任何数 结果都是任何数

0与任何数 结果都是0

0或任何数 结果都是任何数

练习:

使用位运算模拟控制硬件设备。

已知:有8个led灯使用共阴极的接法连接在同一组GPIO上,初始状态未知。

灯的编号 76543210

1.将1357号灯点亮

2.将6号灯点亮

3.将5号灯熄灭

#include <stdio.h>

int main(int argc, const char *argv[])
{
	unsigned char led = 0;//初始状态全熄灭
	//1.点亮1357号灯
	//led = 0x55;//这样操作不好 会影响到其他灯的状态
	
	//如果不想影响其他灯 就需要用位运算了
	led = led | 0xAA;
	printf("led = %#x\n", led);//0xAA

	//2.将6号灯点亮
	//led = led | 0x40;
	led = led | (1<<6);//这样操作就无需计算数了
	printf("led = %#x\n", led);//0xEA

	//3.将5号灯熄灭
	//led = led & 0xDF;
	led = led & ~(1<<5);
	printf("led = %#x\n", led);//0xCA

	return 0;
}

3.8 条件运算符

?:

也是C语言中唯一一个三目运算符。

格式:

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

执行逻辑:

先执行表达式1,如果表达式1为真,则执行表达式2,否则执行表达式3.

逻辑和if…else语句特别像。

例:

#include <stdio.h>

int main(int argc, const char *argv[])
{
	int a = 10;
	int b = 20;
	int c = 0;

	c = (a<b ? ++a : ++b);

	printf("c = %d  a = %d  b = %d\n", c, a, b);//11 11 20

	//上面的语句等价与
	if(a<b){
		c = ++a;
	}else{
		c = ++b;
	}

	return 0;
}

3.9 赋值运算符

=

一般形式:

左 = 右

注意是将右边的值赋值给左边。

注意 = 和 == 的区别。

复合赋值运算符

+= -= *= 等

a+=b <==> a = a+b;

a-=b <==> a = a - b;

其他同理。。

在这里插入图片描述

3.10 sizeof运算符

sizeof是用来计算变量或者类型占用的内存空间的大小的。单位 字节

使用格式:sizeof(变量名或者类型名)  //会返回计算的结果

注意:sizeof的用法和函数调用很像,但是要切记 sizeof 不是函数调用

例:

#include <stdio.h>

int main(int argc, const char *argv[])
{
	char a;
	short b;
	int c;
	long d;
	long long e;
	float f;
	double g;
	//64位系统sizeof返回的是一个long类型
	//32位系统sizeof返回的是一个int类型
	printf("sizeof(char) = %ld  sizeof(a) = %ld\n", sizeof(char), sizeof(a));//1
	printf("sizeof(short) = %ld  sizeof(b) = %ld\n", sizeof(short), sizeof(b));//2
	printf("sizeof(int) = %ld  sizeof(c) = %ld\n", sizeof(int), sizeof(c));//4
	printf("sizeof(long) = %ld  sizeof(d) = %ld\n", sizeof(long), sizeof(d));//4 或 8
	printf("sizeof(long long) = %ld  sizeof(e) = %ld\n", sizeof(long long), sizeof(e));//8
	printf("sizeof(float) = %ld  sizeof(f) = %ld\n", sizeof(float), sizeof(f));//4
	printf("sizeof(double) = %ld  sizeof(g) = %ld\n", sizeof(double), sizeof(g));//8

	long ret1 = sizeof(int);//可以保存sizeof计算的结果
	printf("ret1 = %ld\n", ret1);

	int ret2 = sizeof(int);//这样写也可以 会做隐式强转
	printf("ret2 = %d\n", ret2);

	return 0;
}

3.11 逗号运算符

(,) ----不常用,了解即可

所谓的逗号运算符,就是用逗号连接多个表达式

执行逻辑就是从左到右依次运算,最后一个表达式的结果就是整个逗号运算符表达式的结果。

格式:

(表达式1,表达式2,表达式3,…,表达式n);

例:

#include <stdio.h>

int main(int argc, const char *argv[])
{
	int a = 10;
	int b = 20;
	int c = 30;
	int d = 0;

	d = (++a, ++b, ++c);//从左到右依次运算 ++c的结果 就是整个表达式的结果
	printf("a = %d,  b = %d,  c = %d,  d= %d\n", a, b, c, d);//11 21 31 31

	//如果是逗号运算符 一定要用括号扩起来
	d = ++a, ++b, ++c;//这就不是逗号运算符了
	//只是从左到右依次运算  d 中保存的 ++a 的结果
	printf("a = %d,  b = %d,  c = %d,  d= %d\n", a, b, c, d);//12 22 32 12

	return 0;
}

3.12 运算符的优先级问题

如果在写复杂的表达式的时候,分不清优先级,可以使用 () 来保证正确

()的优先级是最高的,括号加多了不算错 只要写的对就可以

((5+(6*7))-8)

运算符的优先级参考下图

在这里插入图片描述

优先级顺口溜:

单算移关与,异或逻条赋。

思考:

如何交换两个变量的值。

#include <stdio.h>

int main(int argc, const char *argv[])
{
	int m = 10;
	int n = 20;

#if 0
	//方法1:三杯水交换 需要借助临时变量--最常用
	int temp = m;
	m = n;
	n = temp;
#endif

#if 0
	//方法2: 通过加减的方式实现
	//这样操作数据小的时候 可以实现 但是如果两个数都比较大
	//就可能出现数据溢出的情况
	m = m+n;
	n = m-n;
	m = m-n;
#endif

	//方法3:三次异或实现两个数的交换 没有溢出的风险,
	//且能不是用第三个变量实现两个数的交换
	m = m ^ n;
	n = m ^ n;
	m = m ^ n;

	printf("m = %d, n = %d\n", m, n);//20  10

	return 0;
}

b = %d, c = %d, d= %d\n", a, b, c, d);//12 22 32 12

return 0;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值