作者介绍:友友们好我是沐曦希,可以叫我小沐💕
作者主页:沐曦希的个人博客主页.🎉
作者的gitee:https://gitee.com/muxi-c-language.
零基础学习C语言系列:
🎈 https://blog.csdn.net/m0_68931081/category_11742786.html.
🎉小沐和友友们一样喜欢编辑,天天敲代码🤭,沉迷学习,日渐消瘦。很荣幸能向大家分享我的所学,和大家一起进步,成为合格的卷王。✨如果文章有错误,欢迎在评论区✏️指正。那么开始今天的学习吧!😘
文章目录
🎈操作符
指令系统的每一条指令都有一个操作符,它表示该指令应进行什么性质的操作。不同的指令用操作符这个字段的不同编码来表示,每一种编码代表一种指令。
其中操作符分为:
- 算术操作符
2.移位操作符
3.位操作符
4.赋值操作符
5.单目操作符
6.关系操作符
7.逻辑操作符
8.条件操作符
9.逗号表达式
10.下标引用、函数调用和结构成员
🎈算术操作符
+ - *(乘) /(除) %(取模)
注意:1.✏️除了% 操作符之外,其他的几个操作符可以作用于整数和浮点数。
#include<stdio.h>
int main()
{
int a = 12;
int x = 5;
float b = 7.0;
float c = -6.0;
float d = b + c;
float e = b - c;
float f = b * c;
float g = b / c;
int ret = a % x;
printf("d=%f\ne=%f\nf=%f\ng=%f\nret=%d", d, e, f, g, ret);
return 0;
}
2.✏️对于/ 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。
#include<stdio.h>
int main()
{
int a = 20;
int b = 10;
int c = 20.0;
int d = 10.0;
int x = a / b;
float y = c / d;
printf("x=%d\ny=%f", x, y);
return 0;
}
3.✏️% 操作符的两个操作数必须为整数。返回的是整除之后的余数。
#include<stdio.h>
int main()
{
int a = 8;
int b = 3;
int c = a % b;
printf("%d", c);
return 0;
}
🎈移位操作符
移位操作符针对的是二进制,所以移动的是二进制,每次运算时,第一步需要转换成对应的二进制,再进行移位。
<< 左移操作符
>> 右移操作符
注:移位操作符的操作数只能是整数。
✨左移操作符
移位规则:
左边抛弃、右边补0
#include<stdio.h>
int main()
{
int num = 2;
printf("num<<1=%d", num << 1);
return 0;
}
当num=-2时:
#include<stdio.h>
int main()
{
int num = -2;
printf("num<<1=%d", num << 1);
return 0;
}
左移一位相当于该数字乘于2,
✨右移操作符
右移操作符相对复杂一点。分为逻辑移位和算术移位。在转换成二进制时,二进制的第一个数字表示正负,即当第一个数字为0时,该数字为正,为1时,该数字为负
例如:
✏️小知识:整数的二进制表示有三种方式:原码,反码,补码。
正整数的原码,反码和补码相同。
负整数的原码,反码和补码不相同。
其中在存储时候,存储的是补码。
🎉逻辑移位
移位规则:
左边用0填充,右边丢弃
#include<stdio.h>
int main()
{
int num = -2;
int a = num >> 1;
printf("%d", a);
return 0;
}
🎉算术移位
移位规则:
左边用原该值的符号位填充,右边丢弃
#include<stdio.h>
int main()
{
int num = -2;
int a = num >> 1;
printf("%d", a);
return 0;
}
小沐用的编译器支持的是算术右移。
警告⚠ :
对于移位运算符,不要移动负数位,这个是标准未定义的。(浮点数也不行)
例如:
int num = 10;
num>>-1;//error
右移一位相当于除与2。
🎈位操作符
位操作符是二进制的运算,故与移位操作符一样,运算的第一步应讲操作数转换成二进制。位操作符只适用于整型。
位操作符有:
& //按位与
| //按位或
^ //按位异或
注:他们的操作数必须是整数。
🎉&–按位与
运算规则:有零则为零,同为一才为一。✏️
0&0=0 1&0=0 1&1=0 0&1=0
例如:
#include<stdio.h>
int main()
{
int a = 3;
int b = -5;
int c = a & b;
printf("%d", c);
return 0;
}
🎉|–按位或
运算规则:有1则为1,同为零才为零。✏️
1|1=1 1|0=1 0|0=1 0|1=1
例如:
#include<stdio.h>
int main()
{
int a = 3;
int b = -5;
int c = a | b;
printf("%d", c);
return 0;
}
🎉^–按位异或
运算规则:相同为0,不相同为1。✏️
1^0=1 0^1=1 0^0=0 1^1=0
例如:
#include<stdio.h>
int main()
{
int a = 3;
int b = -5;
int c = a ^ b;
printf("%d", c);
return 0;
}
练习:
不能创建临时变量(第三个变量),实现两个数的交换。
//代码一
#include<stdio.h>
int main()
{
int a = 3;
int b = 5;
printf("交换前:a=%d,b=%d\n", a, b);
a = a + b;
b = a - b;
a = a - b;
printf("交换后:a=%d,b=%d\n",a, b);
return 0;
}
代码一容易溢出,当a和b都很大时,容易导致a=a+b溢出。
故:
//代码二
#include <stdio.h>
int main()
{
int a = 10;
int b = 20;
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("a = %d b = %d\n", a, b);
return 0;
}
通过:
3^3=0 0^5=5 a^a=0 0^a=a
即3^3^5=0^5=5 3^5^3=5
则按位异或支持交换律。
🎈赋值操作符
在写代码时候可以通过赋值操作符给变量赋值,从而得到想要的结果。
int weight=120//初始化
weight=90//赋值//注:初始化和赋值不一样
int high=175//初始化
high=185///赋值
//赋值操作符可以连续使用,比如:
int a = 10;
int x = 0;
int y = 20;
a = x = y+1;//连续赋值
//先x=y+1=20+1=21,后a=x=21
//这样的代码感觉怎么样?
//那同样的语义,你看看:
x = y+1;
a = x;
//这样的写法是不是更加清晰爽朗而且易于调试。
✨复合赋值操作符
复合赋值操作符的运算规则和前面的类似。
+= -=
*= /= %=
>>= <<=
&= |= ^=
这些运算符都可以写成复合的效果。
int a+=5//a=a+5
int a-=5//a=a-5
int a*=5//a=a*5
int a/=5//a=a/5
int a%=5//a=a%5
int a>>=5//a=a>>5
int a<<=5//a=a<<5
int a&=5//a=a&5
int a|=5//a=a|5
int a^=5//a=a^5
🎈单目操作符
单目操作符只有一个操作数。
✨单目操作符介绍
! 逻辑反操作
- 负值
+ 正值
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
-- 前置、后置--
++ 前置、后置++
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
//! 逻辑反操作
#include<stdio.h>
int main()
{
int flag = 1;
if (!flag)//flag为假,进入if语句
{
printf("是沐曦希呀\n");
}
if (flag)//flag为真,进入if语句
{
printf("是小沐呀\n");
}
return 0;
}
// -(负值) +(正值)
//负负得正 正正得正 负正得负
#include<stdio.h>
int main()
{
int a = -10;
int b = +a;
int c = -a;
printf("b=%d\nc=%d\n", b, c);
return 0;
}
//&--取地址操作符
#include<stdio.h>
int main()
{
int a = 0;
printf("%p\n", &a);//打印a的地址
return 0;
}
//sizeof 操作数的类型长度(以字节为单位)
#include<stdio.h>
int main()
{
int a = 10;
int n = sizeof(a);//计算的是a所占的内存的大小,单位是字节
printf("n=%d\n", n);
//szieof是一个单目操作符
//计算的是变量所占内存空间的大小
int set = sizeof(int);
//计算类型所创建的变量所占据空间的大小,单位是字节
printf("set=%d\n", set);
int sz = sizeof a;//操作符可以省略变量的(),但是类型不能省去
printf("sz=%d\n", sz);
return 0;
}
//~ 对一个数的二进制按位取反//即将0变成1,1变成0
#include<stdio.h>
int main()
{
int a = 0;
printf("%d\n", ~a);
return 0;
}
#include<stdio.h>
int main()
{
int a = 3;
printf("%d\n", ~a);
return 0;
}
//++ 前置、后置++
#include<stdio.h>
int main()
{
int a = 3;
int b = ++a;//前置++,先++,后使用//a=a+1,b=a
int c = a++;//后置++,先使用,后++//c=a,a=a+1
printf("a=%d,b=%d,c=%d", a, b, c);
return 0;
}
//-- 前置、后置--
#include<stdio.h>
int main()
{
int a = 3;
int b = --a;//前置--,先--,后使用//a=a-1,b=a
int c = a--;//后置--,先使用,后--//c=a,a=a-1
printf("a=%d,b=%d,c=%d", a, b, c);
return 0;
}
#include<stdio.h>
int main()
{
int a = 10;
printf("%d\n", a--);//后置--
printf("%d\n", a);
int i = 0;
for (i = 0; i < 3; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 0; i < 3; ++i)
{
printf("%d ", i);
}//在for语句中前置和后置无区别,只是前置效率高。
return 0;
}
//* 间接访问操作符(解引用操作符)//通常与指针一起使用
#include<stdio.h>
int main()
{
int a = 10;
int* p = &a;
*p = 20;//a=20
printf("a=%d\n", a);
printf("*p=%d\n", *p);
printf("p=%p\n", p);
return 0;
}
//(类型) 强制类型转换//即强制将一种类型转换成另一种类型
#include<stdio.h>
int main()
{
int a = (int)3.14;
printf("%d\n", a);
return 0;
}
✨sizeof 和 数组
初学C语言时,经常用到sizeof来求数组的大小和元素个数等。
需要区别strlen和sizeof。
sizeof是一个单目操作符,不是一个函数。
strlen是一个库函数,头文件为string.h,是用来求字符串的长度。
例如:
#include<stdio.h>
#include<string.h>
void test1(int arr[])
{
printf("arr[]=%d\n", sizeof(arr));
}
void test2(char ch[])
{
printf("ch[]=%d\n", sizeof(ch));
}
int main()
{
int arr[10] = { 0 };
char ch[10] = { 0 };
printf("arr[10]=%d\n", sizeof(arr));
printf("ch[10]=%d\n", sizeof(ch));
test1(arr);
test2(ch);
return 0;
}
注意:1.指针变量不管所指的变量是什么类型,其大小都是4或者8个字节。✏️
当配置是x86时,大小为4个字节;配置为x64时,大小为8个字节。
2.数组作为参数传参时候,传的是数组的首元素的地址。
小知识:
//strcmp是用来比较字符串的内容
//strcpy是用来拷贝内容的
#include<stdio.h>
#include<string.h>
int main()
{
char arr[10] = { 0 };
char ch[5] = "abcd";
strcpy(arr, "母亲节快乐!");
printf("%d\n", sizeof(ch));
printf("%d\n", strlen(ch));
if (~strcmp(ch, "abc"))
{
printf("祝小沐的妈妈");
}
printf("%s\n", arr);
return 0;
}
strcmp函数是string compare(字符串比较)的缩写,用于比较两个字符串并根据比较结果返回整数。基本形式为strcmp(str1,str2),若str1=str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数。
strlen是用来求字符串的长度。
strlen遇到’\0’则停止并返回,只会计算‘\0’之前的元素个数。
sizeof可以求变量(类型)所占空间的大小。
🎈关系操作符
>
>=
<
<=
!= 用于测试“不相等”
== 用于测试“相等”
这些关系运算符比较简单,但是我们要注意一些运算符使用时候的陷阱。
例如:在编程的过程中把==写成=,导致错误
#include<stdio.h>
int main()
{
int a = 0;
if (a = 1)
{
printf("hehe\n");
}
if (a == 2)
{
printf("haha\n");
}
return 0;
}
if("abc"=="abcdef")//这样写是比较两个字符串的首字符的地址
//比较字符串用strcmp
🎈逻辑操作符
逻辑操作符只关注真假,真则返回1,假则返回0。
&& 逻辑与
|| 逻辑或
区分 逻辑与(&&) 和 按位与(&)
区分 逻辑或(||) 和 按位或(|)
#include<stdio.h>
int main()
{
printf("%d\n", 1 & 2);
printf("%d\n", 1 && 2);
printf("%d\n", 1 | 2);
printf("%d\n", 1 || 2);
return 0;
}
//练习1
#include <stdio.h>
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ && ++b && d++;//后置++,因为a=0,即为假,故后面的++b和d++不会运行,只运行a=a+1
printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
return 0;
}
//练习2
#include <stdio.h>
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++||++b||d++;//因为前置++b,b=3,故为真,即运行a++,++b和d++
printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
return 0;
}
&&–左边为假,即为假,则右边就不用计算了。
||–左边为真,即为真,则右边就不用计算了。
🎈条件操作符
条件操作符也叫三目操作符
exp1 ? exp2 : exp3
//使用条件表达式实现找两个数中较大值。
#include<stdio.h>
int main()
{
int a = 10;
int b = 20;
printf("%d\n", a > b ? a : b);
return 0;
}
if (a > 5)
b = 3;
else
b = -3;
//转换成条件表达式
#include<stdio.h>
int main()
{
int b = 0;
int a = 0;
b = (a > 5 ? 3 : -3);
return 0;
}
🎈逗号表达式
exp1, exp2,exp3...expN
逗号表达式,就是用逗号隔开的多个表达式。
逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。
//代码1
int a = 1;
int b = 2;
int c = (a>b, a=b+10, a, b=a+1);//逗号表达式
//c是多13
//代码2
if (a =b + 1, c=a / 2, d > 0)//if(d>0)
//代码3
a = get_val();
count_val(a);
while (a > 0)
{
//业务处理
a = get_val();
count_val(a);
}
//如果使用逗号表达式,改写:
while (a = get_val(), count_val(a), a>0)
{
//业务处理
}
🎈下标引用、函数调用和结构成员
✨[ ] 下标引用操作符
操作数:一个数组名 + 一个索引值
#include<stdio.h>
int main()
{
int arr[10] = { 0 };
arr[7] = 8;//[]是下标引用操作符(双目操作符:arr和7是操作数)
7[arr] = 9;//arr[7]-->*(arr+7)-->*(7+arr)-->7[arr]//arr是数组的首元素地址
//arr+7就是跳过7个元素,指向第8个元素。//*(arr+7)就是第8个元素
printf("%d\n", arr[7]);
printf("%d\n", 7[arr]);
return 0;
}
✨( ) 函数调用操作符
接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。
#include <stdio.h>
void test1()
{
printf("hehe\n");
}
void test2(const char* str)
{
printf("%s\n", str);
}
int main()
{
test1(); //实用()作为函数调用操作符。//操作数只有一个,即为test1
test2("hello");//实用()作为函数调用操作符。//操作数有两个,test2和"hello"。
return 0;
}
int c=Add(a,b);//()是函数调用操作符,操作数:Add,a,b
//函数调用操作符()的操作数至少有一个,即为函数名
✨访问一个结构的成员
. 结构体.成员名
-> 结构体指针->成员名
#include <stdio.h>
struct Stu
{
char name[10];
int age;
char sex[5];
double score;
};
void set_age1(struct Stu stu)
{
stu.age = 18;
}
void set_age2(struct Stu* pStu)
{
pStu->age = 18;//结构成员访问
}
int main()
{
struct Stu stu;
struct Stu* pStu = &stu;//结构成员访问
stu.age = 20;//结构成员访问
set_age1(stu);
pStu->age = 20;//结构成员访问
set_age2(pStu);
return 0;
}
#include <string.h>
#include<stdio.h>
struct Stu
{
char name[20];
int age;
double score;
};
void set_stu(struct Stu* ps)
{
//strcpy((*ps).name, "zhangsan");
//(*ps).age = 20;
//(*ps).score = 100.0;
strcpy(ps->name, "zhangsan");
ps->age = 20;
ps->score = 100.0;
}
void print_stu(struct Stu* ps)
{
printf("%s %d %lf\n", ps->name, ps->age, ps->score);
}
int main()
{
struct Stu s = { 0 };
set_stu(&s);
print_stu(&s);
return 0;
}
🎉写在最后
那么今天的学习就到这里了。友友们觉得不错的可以给个关注,点赞或者收藏哦!😘感谢各位友友们的支持。以下的代码希望各位大佬们自行检验哦,毕竟亲手操作让记忆更加深刻。
你的❤️点赞是我创作的动力的源泉
你的✨收藏是我奋斗的方向
你的🙌关注是对我最大的支持
你的✏️评论是我前进的明灯
创作不易,希望大佬你支持一下小沐吧😘
下一期见了!