商城网站系,岳阳公司网站建设,淘宝官网首页电脑版登录入口,如何自己做官网首页#x1f31e; “等春风得意#xff0c;等时间嘉许#xff01;” 接下来#xff0c;我们把操作符没学完的继续学完#xff01; 操作符详解 6.2sizeof和数组 7.关系操作符8.逻辑操作符9.条件操作符10.逗号表达式11.下标引用、函数调用和结构成员12.表达式求值12.1隐式类型转… “等春风得意等时间嘉许” 接下来我们把操作符没学完的继续学完 操作符详解 6.2sizeof和数组 7.关系操作符8.逻辑操作符9.条件操作符10.逗号表达式11.下标引用、函数调用和结构成员12.表达式求值12.1隐式类型转换12.2算术转换12.3 操作符的属性 6.2sizeof和数组
我们来看一下下面这段代码
#define _CRT_SECURE_NO_WARNINGS 1
#include stdio.h
void test1(int arr[])//相当于int *arr
//传的是数组首元素的地址
{printf(%d\n, sizeof(arr));//指针的大小在32位的编译器里是4个字节在64位的编译器里是8个字节
}
void test2(char ch[])
{printf(%d\n, sizeof(ch));
}
int main()
{int arr[10] { 0 };char ch[10] { 0 };printf(%d\n, sizeof(arr));//数组有10个整型元素所以结果是40printf(%d\n, sizeof(ch));//数组有10个字符型元素结果是10test1(arr);test2(ch);return 0;
}7.关系操作符 关系操作符 !用于测试不相等 用于测试相等 注不要把和混起来❗ ✅用于测试相等用于赋值。
8.逻辑操作符 逻辑操作符逻辑与操作符 ||逻辑或操作符 #define _CRT_SECURE_NO_WARNINGS 1
#include stdio.h
int main()
{int month 0;scanf(%d,month);if (month 3 month 5){printf(春季\n);}if (month 12 || month 1 || month 2){printf(冬季\n);}return 0;
}这里我们来看一道题
#include stdio.h
int main()
{int i 0, a 0, b 2, c 3, d 4;i a b d;//a先得到0对于操作符前面为假后面就不会计算了printf(a %d\nb %d\nc %d\nd %d\n, a, b, c, d);//1 2 3 4printf(i %d\n, i);return 0;
}这里如果我们将a的值变为1那么结果是什么呢
#include stdio.h
int main()
{int i 0, a 1, b 2, c 3, d 4;i a b d;//i 1341printf(a %d\nb %d\nc %d\nd %d\n, a, b, c, d);printf(i %d\n, i);return 0;
}同样的如果我们这里将改为||结果又是怎么样的呢
#include stdio.h
int main()
{int i 0, a 1, b 2, c 3, d 4;i a || b || d;//a先得到结果1表达式已经为真后面不计算b和d的值不变printf(a %d\nb %d\nc %d\nd %d\n, a, b, c, d);printf(i %d\n, i);return 0;
}9.条件操作符 条件操作符表达式1 ?表达式2:表达式3 ✅唯一 一个三目操作符。 表达式1为真表达式2的结果为整个表达式的结果表达式3不算. 表达式1为假表达式3的结果为整个表达式的结果表达式2不算。 如果我们这里需要计算出两个数的最大值按照前面所学的我们可能会这样写
#define _CRT_SECURE_NO_WARNINGS 1
#include stdio.h
int main()
{int a 0;int b 0;int m 0;scanf(%d%d, a, b);if (a b)m a;elsem b;printf(%d\n, m);return 0;
}但是这里如果我们用上条件操作符就会省很多事❗
#define _CRT_SECURE_NO_WARNINGS 1
#include stdio.h
int main()
{int a 0;int b 0;scanf(%d%d, a, b);printf(%d\n, a b ? a : b);return 0;
}10.逗号表达式 逗号表达式表达式1,表达式2,表达式3...... ✅逗号表达式会从左往右依次执行整个表达式的结果是最后一个表达式的结果。 那我们一起看看下面这段代码的运行结果是怎么样的呢
#include stdio.h
int main()
{int a 1;int b 2;int c (a b, a b 5, a, b a 10);// 0 7 7 17printf(%d\n, c);return 0;
}示例
#include stdio.h
int main()
{int a 0;while (a 0){a get_val();count_val(a);}//上述while循环可以改写为以下的代码/*while (a get_val(), count_val(a), a0){}*/return 0;
}11.下标引用、函数调用和结构成员 下标引用操作符[] 操作数为一个数组名一个索引值 #include stdio.h
int main()
{int arr[] { 1,2,3,4,5,6,7,8,9,10 };//诸如0 1 2 3 4 5 6 7 8 9 称为索引值printf(%d\n, arr[2]);//[]-下标引用操作符return 0;
}函数调用操作符() 接受一个或多个操作数第一个操作数是函数名剩余的操作数是传递给函数的参数。 #include stdio.h
int add(int x, int y)
{return x y;
}
int main()
{printf(%d, add(3, 4));//()函数调用操作符最少有一个操作数为函数名return 0;
}访问一个结构体成员 结构体.成员名 结构体指针-成员名 #include stdio.h
struct Book
{char name[20];int price;
};
int main()
{struct Book b { 明解C语言,50 };printf(%s %d\n, b.name, b.price);return 0;
}以下三种写法得到的结果相同
#include stdio.h
struct Book
{char name[20];int price;
};
void Print(struct Book* pb)
{printf(%s %d\n, (*pb).name, (*pb).price);printf(%s %d\n, pb-name, pb-price);
}
int main()
{struct Book b { 明解C语言,50 };printf(%s %d\n, b.name, b.price);Print(b);return 0;
}12.表达式求值 表达式求值的顺序一部分是由操作符的优先级和结合性来决定的。同样有些表达式的操作数在求值的过程中可能需要转换为其他类型。 12.1隐式类型转换 C的整型算术运算总是至少以缺省整形类型的精度来进行。为了获取这个精度表达式中的字符和短整型操作数之间被转换为普通整型这样的类型转换为整型提升。 整型提升是按照变量的数据类型的符号位来提升的。 #include stdio.h
int main()
{char a 5;//00000101//整型提升00000000000000000000000000000101char b 126;//01111110//整型提升00000000000000000000000001111110char c a b;//c: 00000000000000000000000010000011//10000011//c整型提升11111111111111111111111110000011//反码 11111111111111111111111110000010//原码 10000000000000000000000001111101//-148163264-125printf(%d\n, c);return 0;
}整型提升的意义 表达式的整型运算要在CPU的相应运算器件内执行CPU内整型运算器(ALU)的操作数的字节长度。 一般就是int的字节长度同时也是CPU的通用寄存器的长度。 因此即使两个char类型的相加在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。 通用CPUgeneral-purpose CPU是难以直接实现两个8比特字节直接相加运算虽然机器指令 中可能有这种字节相加指令。所以表达式中各种长度可能小于int长度的整型值都必须先转 换为int或unsigned int然后才能送入CPU去执行运算。 #include stdio.h
int main()
{char c 1;printf(%d\n, sizeof(c));printf(%d\n, sizeof(c));printf(%d\n, sizeof(-c));
//c只要参加表达式运算就会发生整型提升return 0;
}12.2算术转换 如果某个操作符的各个操作数属于不同的类型那么除非其中一个操作数的转换为另一个操作数的类型否则操作就无法进行。下面的层次体系称为寻常算术转换。 long double、double、float、unsigned long int、long int、unsigned int、int 如果某个操作数的类型在上面这个列表中排名较低那么首先要转换为另外一个操作数的类型后执行运 算。 ❗警告 但是算术转换要合理要不然会有一些潜在的问题。 12.3 操作符的属性
复杂表达式的求值有三个影响的因素:
操作符的优先级操作符的结合性是否控制求值顺序。
✅两个相邻的操作符先执行哪个取决于他们的优先级。如果两者的优先级相同取决于他们的结合性。 操作符的优先级
操作符描述结合性是否控制求值顺序()聚组/否()函数调用左结合性否[ ]下标引用左结合性否.访问结构成员左结合性否-访问结构指针成员左结合性否后缀自增左结合性否- -后缀自减左结合性否!逻辑反右结合性否~按位取反右结合性否单目表示正值左结合性否-单目表示负值右结合性否前缀自增右结合性否- -前缀自减右结合性否*间接访问右结合性否取地址右结合性否sizeof取其长度以字节表示右结合性否(类型)类型转换右结合性否*乘法左结合性否/除法左结合性否%整数取模左结合性否加法左结合性否-减法左结合性否左移位左结合性否右移位左结合性否大于左结合性否大于等于左结合性否小于左结合性否小于等于左结合性否等于左结合性否!不等于左结合性否位与左结合性否^位异或左结合性否I位或左结合性逻辑与左结合性是II逻辑或左结合性是?:条件操作符/是赋值左结合性否以…加右结合性否-以…减右结合性否*以…乘右结合性否/以…除右结合性否%以…取模右结合性否以…左移右结合性否以…右移右结合性否以…与右结合性否^以…异或右结合性否I以…或右结合性否,逗号左结合性是
对于下面的这个表达式表达式的计算顺序就不一定了
a* b c * d e * f;❌同样的对于下面的这个表达式
c --c;操作符的优先级只能决定自减的运算在的运算的前面但是我们并没有办法得知操作符的左操作数的获取在右操作数之前还是之后求值所以结果是不可预测的是有歧义的。 我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径那这个表达式就是存在问题的我们在写程序的时候要避免写出这样的代码 好啦关于操作符的知识点到这里就结束啦后期会继续更新C语言的相关知识欢迎大家持续关注、点赞和评论❤️❤️❤️