C learning_13 操作符前篇(条件操作符、 逗号表达式、 下标引用、函数调用和结构成员、 表达式求值)

news2024/11/26 11:45:51

目录

         条件操作符

逗号表达式

下标引用、函数调用和结构成员

1. [ ] 下标引用操作符 

2. ( ) 函数调用操作符

3. 访问一个结构的成员

表达式求值

1.隐式类型转换

2.算术转换

3.操作符的属性


条件操作符

        条件操作符是一种用于简化条件表达式的运算符。它通常表示为问号' ? '和冒号' : '。条件操作符需要三个操作数(条件操作符又称三目运算符)。它的语法如下:

condition ? expression1 : expression2

        其中,condition是一个布尔表达式,expression1和expression2可以是任何合法的表达式,它们的类型可以不同。如果condition的值为true,则返回expression1的值;否则返回expression2的值。

例如:

int a = 10, b = 20;
int max = (a > b) ? a : b; // 如果a>b,返回a的值,否则返回b的值,结果为20

        条件操作符通常用于简化if-else语句,使代码更加简洁、清晰。

转化的if-else语句
int a = 10, b = 20;
if(a>b)
    max = a;
else
    max = b;
// 如果a>b,返回a的值,否则返回b的值,结果为20

逗号表达式

        逗号表达式,就是用逗号隔开的多个表达式。 逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。

expr1, expr2, ... , exprN

其中expr1, expr2, ... , exprN都是表达式,从左到右依次执行,整个表达式的结果是exprN

例如:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	int a = 1;
	int b = 2;
	int c = (a > b, a = b + 10, a, b = a + 1);//逗号表达式
	return 0;
}

c 的值由逗号表达式计算得到,先计算表达式 a > b,这个表达式的值为假(即 0);然后计算表达式 a = b + 10,它将 a 的值赋为 12;然后再执行a表达式,a的值为12;逗号表达式的值为最后一个表达式的值,即表达式 b = a + 1 的值,它将 b 的值赋为 13。

小练习一下

#include<stdio.h>
int main()
{
	int a = 0;
	int b = 0;
	double c = 0.0;
	int d = 0;
	if (a = b + 1, c = a / 2.0, d > 0)
	{
		printf("NO.1\n");
	}
	else
	{
		printf("NO.2\n");
	}
	printf("%d %d %.1lf %d\n", a, b, c, d);
	return 0;
}

        这是一个if-else语句,其中包含了一个逗号表达式。a = b + 1表示将b的值加1并赋给a;

c = a / 2.0表示将a除以2,并将结果赋给c;d > 0表示判断d是否大于0,逗号表达式的最后一个表达式满足,则执行if语句中的代码,输出"NO.1";否则,执行else中的代码,出"NO.2"。

然后在输出a、b、c、d的值,验证逗号表达式的执行顺序。

代码改写:使用逗号表达式、do-while语句改写
a = get_val();
count_val(a);//代码冗余
while (a > 0)
{
    //功能实现
	a = get_val();
	count_val(a);
}
//do-while语句
do
{
    //功能实现
    a = get_val()
    count_val(a)
}while(a>0);

//逗号表达式
while (a = get_val(), count_val(a), a>0)
{
    //功能实现
}

下标引用、函数调用和结构成员

1. [ ] 下标引用操作符 

操作数:一个数组名 + 一个索引值

int arr[10];//创建数组
arr[9] = 10;//实用下标引用操作符[ ]。
//[ ] 的两个操作数是arr和 9。

2. ( ) 函数调用操作符

接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。

#include <stdio.h>
void test1()
{
	printf("hehe\n");
}
void test2(const char* str)
{
	printf("%s\n", str);
}
int main()
{
	test1();            //实用 () 作为函数调用操作符。
	test2("hello world!");//实用 () 作为函数调用操作符。
	// () 的两个操作数是函数名和参数。
	// () 至少有一个操作数,因为函数可能无参数
	return 0;
}

3. 访问一个结构的成员

.            结构体.成员名

->         结构体指针->成员名

#include <stdio.h>
struct Stu
{
	char name[10];
	int age;
	char sex[5];
};
void set_age1(struct Stu stu)
	{
		stu.age = 18;//结构成员访问   .操作符
	}
	void set_age2(struct Stu* pStu)
	{
		pStu->age = 18;//结构成员访问 ->操作符
	}
int main()
{
	struct Stu stu;
	set_age1(stu);
	set_age2(&stu);
	return 0;
}

表达式求值

        表达式求值的顺序一部分是由操作符的优先级和结合性决定。 同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。

1.隐式类型转换

        C的整型算术运算总是至少以缺省整型类型的精度来进行的。 为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升

        表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。 因此,即使两个char类型或者int类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长 度。 通用CPU(general-purpose CPU)是难以直接实现两个8(或者16)比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或unsigned int,然后才能送入CPU去执行运算。

如何进行整体提升

整形提升是按照变量的数据类型的符号位来提升的。

#include<stdio.h>
int main()
{
	
	char c1 = 5;
	//0000 0000 0000 0000 0000 0000 0000 0101
	//由于是c1是char类型 - 只有八个比特位 - 发生截断
	//0000 0101 - c1
	char c2 = 127;
	//0000 0000 0000 0000 0000 0000 0111 1111
	//由于是c2是char类型 - 只有八个比特位 - 发生截断
	//0111 1111 - c2
	char c3 = c1 + c2;
	/*
		0000 0101 - c1
		0111 1111 - c2
		+_____________
		进行整型提升才能相加
		
		(按照数据的符号位进行提升的,高位补充符号位)
		c1和c2都是有符号数,符号位都是0,高位补0

		0000 0000 0000 0000 0000 0000 0000 0101
		0000 0000 0000 0000 0000 0000 0111 1111
		+______________________________________
		0000 0000 0000 0000 0000 0000 1000 0100
	*/
	//由于c3是char类型 - 只有八个比特位 - 发生截断
	//1000 0100
	
	//由于c3是有符号数,高位是符号位
	//再以十进制的形式打印有符号整数
	//整形提升,高位补充符号位(1)
	//1111 1111 1111 1111 1111 1111 1000 0100 - 补码
	//1111 1111 1111 1111 1111 1111 1000 0011 - 反码
	//1000 0000 0000 0000 0000 0000 0111 1100 - 原码 - -124
	printf("%d\n", c3);
	return 0;
}

小练习

#include<stdio.h>
int main()
{
	char a = 0xb6;
	//0000 0000 0000 0000 0000 0000 1011 0110
	//由于是a是char类型 - 只有八个比特位 - 发生截断
	//1011 0110 - a
	short b = 0xb600;
	//0000 0000 0000 0000 1011 0110 0000 0000 
	//由于是b是short类型 - 只有十六个比特位 - 发生截断
	//1011 0110 0000 0000 - b
	int c = 0xb6000000;
	//1011 0110 0000 0000 0000 0000 0000 0000
	//由于是b是short类型 - 不需要截断
	//1011 0110 0000 0000 0000 0000 0000 0000

	/*
		进行比较 a == 0xb6 - 需要整形提升
		1011 0110 - a
		由于a有符号char数,高位是符号位
		1111 1111 1111 1111 1111 1111 1011 0110 - a
		0000 0000 0000 0000 0000 0000 1011 0110 - 0xb6
		//很明显,两者不相等
	*/
	if (a == 0xb6)
		printf("a");
	/*
		进行比较 b == 0xb600 - 需要整形提升
		1011 0110 0000 0000 - b
		由于b有符号short数,高位是符号位
		1111 1111 1111 1111 1011 0110 0000 0000 - b
		0000 0000 0000 0000 1011 0110 0000 0000  - 0xb600
		//很明显,两者不相等
	*/
	if (b == 0xb600)
		printf("b");
	/*
		进行比较 c == 0xb6000000 - b不需要整形提升
		1011 0110 0000 0000 0000 0000 0000 0000
		由于b有符号int数
		1011 0110 0000 0000 0000 0000 0000 0000 - c
		1011 0110 0000 0000 0000 0000 0000 0000 - 0xb6000000
		//很明显,两者相等
	*/
	if (c == 0xb6000000)
		printf("c");
	return 0;
}

         变量c只要参与表达式运算,就会发生整形提升,表达式 +c ,就会发生提升,所以 sizeof(+c) 是4个字 节. 表达式 -c 也会发生整形提升,所以 sizeof(-c) 是4个字节,但是 sizeof(c) ,就是1个字节。

2.算术转换

        如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类 型,否则操作就无法进行。下面的层次体系称为寻常算术转换。

        如果某个操作数的类型在上面这个列表中排名较低,那么首先要这个排名较低的类型转换为另外一个操作数的类型后执行运算。

 如果我们需要将排名较高的类型变为排名较低的就需要进行强制类型转换。

3.操作符的属性

1. 操作符的优先级

2. 操作符的结合性

3. 是否控制求值顺序

        两个相邻的操作符先执行哪个?取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性。

接下来我们来看看几个表达式是否有无问题

//表达式1 
a*b + c*d + e*f

注释:代码1在计算的时候,由于*+的优先级高,只能保证,*的计算是比+早,但是优先级并不能决定第三个*比第一个+早执行。

a*b
c*d
a*b + c*d
e*f
a*b + c*d + e*f
或者:
a*b
c*d
e*f
a*b + c*d
a*b + c*d + e*
//表达式2 
c + --c;

        注释:同上,操作符的优先级只能决定自减--的运算在+的运算的前面,但是我们并没有办法得知,+操作符的左操作数的获取在右操作数之前还是之后求值,所以结果是不可预测的,是有歧义 的。

//代码3-非法表达式
#include<stdio.h>
int main()
{
    int i = 10;
    i = i-- - --i * ( i = -3 ) * i++ + ++i;
    printf("i = %d\n", i);
    return 0;
}

        这段代码的结果很难预测,因为它包含了多个副作用和未定义行为。具体来说,i-- 和 --i 都是修改了 i 的值的操作,因此使用它们的结果可能会导致 i 的值产生混淆。此外,将 i = -3 置于乘法操作之间也非常危险,因为它依赖于乘法的优先级和结合律。更确切地说,这个表达式中连续的 * 运算符构成了一个不符合常识的乘法表达式。在 i = -3 和 i++ + ++i 之间也存在未定义的行为,因为它们都修改了 i 的值,并且没有指定它们的顺序。最终的结果也可能会因为机器和编译器的差异而不同。但是,一般来说,i 的值将会被改变,并被输出到屏幕上。具体的值取决于编译器的实现,以及计算机的硬件和操作系统环境。

//代码4
#include<stdio.h>
int fun()
{
     static int count = 1;
     return ++count;
}
int main()
{
     int answer;
     answer = fun() - fun() * fun();
     printf( "%d\n", answer);//输出多少?
     return 0;
}

        上述代码 answer = fun() - fun() * fun(); 中我们只能通过操作符的优先级得知:先算乘法, 再算减法。 函数的调用先后顺序无法通过操作符的优先级确定。

//代码5
#include <stdio.h>
int main()
{
 int i = 1;
 int ret = (++i) + (++i) + (++i);
 printf("%d\n", ret);
 printf("%d\n", i);
 return 0;
}

        我们发现在不同的平台的值是不同的,说明这个代码也是有问题的。我们接下来看看在vs平台上它是怎么计算的? 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/525365.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《游戏编程模式》--重访设计模式--学习

序 在线阅读地址&#xff1a; 命令模式 Design Patterns Revisited 游戏设计模式 (tkchu.me) 参考文章&#xff1a; GameDesignPattern_U3D_Version/Assets/002FlyweightPattern at master TYJia/GameDesignPattern_U3D_Version GitHub 看到了没见过的观点&#xff1a;…

我的算法基础实验代码-下篇

第一题 题目介绍 输入一些数值&#xff0c;求出现的次数最多的数。如果有多个并列&#xff0c;则从大到小输出。 解题思路 代码实现 package com.nineWeek;import java.util.*;/*** author WangYH* version 2021.1.3* date 2023/5/7 18:29*/public class NumMostTimes {pu…

第十四届蓝桥杯b组c/c++

D:飞机降落&#xff08;全排列&#xff09; #include<iostream> #include<cstring> using namespace std;const int N 12; int n; struct node{int t, d, l; //t为此飞机的最早降落时间 d为盘旋时间 l为降落所需时间 }p[N]; bool st[N];//DFS求全排列模型 bool d…

【真题解析】系统集成项目管理工程师 2021 年下半年真题卷

本文为系统集成项目管理工程师考试(软考) 2021 年上半年真题&#xff0c;包含答案与详细解析。考试共分为两科&#xff0c;成绩均 ≥45 即可通过考试&#xff1a; 综合知识&#xff08;选择题 75 道&#xff0c;75分&#xff09;案例分析&#xff08;问答题 4 道&#xff0c;75…

ChatGPT 学习与使用总结

ChatGPT 学习与使用总结 最近ChatGPT大火&#xff0c;2023有可能就是AGI元年了。近两个月使用下来&#xff0c;ChatGPT给我最深刻的感觉就是它所具备的理解和思维能力&#xff0c;第一次体验时真的是非常震撼&#xff0c;完全是之前各种『人工智障』智能助理所不能比拟的&…

Windows系统出现蓝屏怎么办?这些方法可以修复!

Windows 系统蓝屏死机&#xff08;BSOD&#xff09;&#xff0c;也被称为“停止错误”&#xff0c;是Windows系统最常见的故障之一。 当Windows遇到严重的故障时就会显示蓝屏&#xff0c;系统崩溃。蓝屏上显示一个停止代码&#xff0c;如"MEMORY_MANAGEMENT"&#xf…

NeRF与三维重建专栏(一)领域背景、难点与数据集介绍

前言 关于该系列专栏&#xff0c;主要介绍NeRF在三维重建中的应用&#xff08;这里我们特指MVS&#xff0c;multi-view stereo&#xff0c;也即输入带位姿的图片&#xff0c;输出三维结构例如点云、mesh等&#xff1b;并且后面的工作也都是围绕MVS with NeRF讨论的。虽然也有w…

人类与ChatGPT:互动中的共同进步

一、ChatGPT的发展历程 1. GPT模型 ChatGPT是由OpenAI推出的一款聊天机器人&#xff0c;其核心技术基于GPT模型。GPT模型&#xff08;Generative Pre-training Transformer&#xff09;是一种基于Transformer结构的预训练语言模型。它在大规模的文本语料库上进行无监督的预训…

解析 ip addr 的输出的内容含义

解读 ip addr 的输出的网络连接信息含义 一、ifconfig 与 ip addr 用过Linux的读者都知道&#xff0c;在Linux查看ip可以使用ifconfig&#xff0c;当然这个ifconfig属于net-tools 工具集&#xff0c;其来源于BSD&#xff0c;Linux从2001年就不对其进行维护了。那我们应该用什…

基于下垂控制的并网逆变器控制MATLAB仿真模型

资源地址&#xff1a; 基于下垂控制的并网逆变器控制MATLAB仿真模型资源-CSDN文库 主要模块&#xff1a; 建议使用MATLAB2021b及以上版本打开&#xff01; 功率计算模块、下垂控制模块、电压电流双环控制模块、虚拟阻抗压降模块 扰动设置&#xff1a; 在0.5秒到2秒始端设置…

微软出品的实用小工具

微软出品的实用小工具 分享一些微软出品的实用小工具&#xff0c;希望对大家有所帮助。 文章目录 微软出品的实用小工具SysinternalsSuite常用工具AutorunsprocdumpProcess Explorer进程监视器 Process MonitorpsloggedonAccessChk示例 PsToolsrdcmanTcpviewVmmap Sysinternals…

数据结构_树与二叉树

目录 1. 树的基本概念 1.1 树的定义 1.2 基本术语 1.3 树的性质 1.4 相关练习 2. 二叉树的概念 2.1 二叉树的概念及其主要特性 2.2 二叉树的存储结构 2.2.1 顺序存储结构 2.2.2 链式存储结构 2.3 相关练习 3. 二叉树的遍历和线索二叉树 3.1 二叉树的遍历 3.1.1 先…

基于微信小程序校内论坛系统

开发工具&#xff1a;IDEA、微信小程序 服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8 项目构建&#xff1a;maven 数据库&#xff1a;mysql5.7 前端技术&#xff1a;vue、uniapp 服务端技术&#xff1a;springbootmybatis-plus 本系统分微信小程序和管理后台两部分&a…

神马网络——IP地址

个人简介&#xff1a;云计算网络运维专业人员&#xff0c;了解运维知识&#xff0c;掌握TCP/IP协议&#xff0c;每天分享网络运维知识与技能。座右铭&#xff1a;海不辞水&#xff0c;故能成其大&#xff1b;山不辞石&#xff0c;故能成其高。个人主页&#xff1a;小李会科技的…

ChatGPT提示词技巧

自计算机问世以来&#xff0c;人类与计算机之间的交互方式已经经历过几个重要的阶段&#xff1a; 指令式交互&#xff08;Command-based Interaction&#xff09; 早期的计算机系统主要采用了指令式交互方式&#xff0c;用户需要输入特定的命令或代码来完成各种任务。这种交…

软件与硬件的联调之小程序与云平台相互通信

软件与硬件的联调之小程序与云平台相互通信 本人专注使用云开发&#xff0c;实现一个前端可以做后端以及整个项目的部署与上线。 如果觉得我讲的好就可以给我点个赞。 #mermaid-svg-xJRh48GCcG2gzlqz {font-family:"trebuchet ms",verdana,arial,sans-serif;font-si…

深度学习之图像分类识别(二):ZFNet

本专栏介绍基于深度学习进行图像识别的经典和前沿模型&#xff0c;将持续更新&#xff0c;包括不仅限于&#xff1a;AlexNet&#xff0c; ZFNet&#xff0c;VGG&#xff0c;GoogLeNet&#xff0c;ResNet&#xff0c;DenseNet&#xff0c;SENet&#xff0c;MobileNet&#xff0c…

我的第一个Electron应用

hello&#xff0c;好久不见&#xff0c;最近笔者花了几天时间入门Electron&#xff0c;然后做了一个非常简单的应用&#xff0c;本文就来给各位分享一下过程&#xff0c;Electron大佬请随意~ 笔者开源了一个Web思维导图&#xff0c;虽然借助showSaveFilePicker等api可以直接操…

【C#】接口实现多态增强版

背景 在实际的生产中&#xff0c;会涉及到需要对接多种相似性较高的系统。具体而言就是业务接口是相同的&#xff0c;但是会出现接口的参数不同的情况。这时做一个对接隔离层就显得优势很明显了。这个隔离层的作用就有了两个基本的作用&#xff1a; 1、单一性&#xff0c;保护我…

【网络】- TCP/IP四层(五层)协议 - 物理层

目录 一、概述 二、物理层的基本概念 三、OSI 参考模型  &#x1f449;3.1 导引型传输媒体  &#x1f449;3.1 导引型传输媒体 一、概述 TCP/IP 在最初定义时&#xff0c;是一个四层的体系结构&#xff0c;包括应用层、传输层、网络层、网络接口层。不过从实质上来讲&#xf…