learn_C_deep_11 (深刻理解整形提升、左移和右移规则、花括号、++和--操作、表达式匹配:贪心算法)

这篇具有很好参考价值的文章主要介绍了learn_C_deep_11 (深刻理解整形提升、左移和右移规则、花括号、++和--操作、表达式匹配:贪心算法)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

深刻理解整形提升

左移和右移规则

如何理解"丢弃"

一个问题

 0x01<<2+3 的值是多少

花括号

++、--操作

表达式匹配:贪心算法


深刻理解整形提升

#include <stdio.h>
int main()
{
	char c = 0;
	printf("sizeof(c): %d\n", sizeof(c)); //1
	printf("sizeof(c): %d\n", sizeof(~c)); //4
	printf("sizeof(c): %d\n", sizeof(c << 1)); //4
	printf("sizeof(c): %d\n", sizeof(c >> 1)); //4
	return 0;
}

learn_C_deep_11 (深刻理解整形提升、左移和右移规则、花括号、++和--操作、表达式匹配:贪心算法)

char类型的c经过按位取反、左移和右移是不是char类型了?为什么char类型的c加了操作符运算求空间大小就不是1了呢?

        无论任何位运算符,目标都是要计算机进行计算的,而计算机中只有CPU具有运算能力(先这样简单理解),但计算的数据, 都在内存中。故,计算之前(无论任何运算),都必须将数据从内存拿到CPU中,拿到CPU哪里呢?毫无疑问,在CPU 寄存器 中。 而寄存器本身,随着计算机位数的不同,寄存器的位数也不同。一般,在32位下,寄存器的位数是32位。 可是,你的char类型数据,只有8比特位。读到寄存器中,只能填补低8位,那么高24位呢? 就需要进行“整形提升”。

        char类型的数据经过按位取反、左移和右移后,仍然是char类型的数据,这些操作不会改变数据的类型。char类型进行操作符运算进行了整形提升,由于寄存器的位数是32位,char类型的变量会提升为int类型,所以求的空间大小就是4个字节。

learn_C_deep_11 (深刻理解整形提升、左移和右移规则、花括号、++和--操作、表达式匹配:贪心算法)

对于vs编译器(图右)上将!c所占空间定为1个字节,我们可以认为这是编译器的bug,因为c参加了运算,必定会进行整形提升,在gcc编译器(图左)下我们就可以发现!c所占空间是4个字节。 

左移和右移规则

learn_C_deep_11 (深刻理解整形提升、左移和右移规则、花括号、++和--操作、表达式匹配:贪心算法)

#include <stdio.h>
int main()
{
	/*
		<<(左移): 最高位丢弃,最低位补零
		>>(右移):
		1. 无符号数:最低位丢弃,最高位补零     [逻辑右移]
		2. 有符号数:最低位丢弃,最高位补符号位 [算术右移]
	*/
	//左移
	unsigned int a = 1;    //0000 0000 0000 0000 0000 0000 0000 0001 - 1
	printf("%u\n", a << 1);//0000 0000 0000 0000 0000 0000 0000 0010 - 2
	printf("%u\n", a << 2);//0000 0000 0000 0000 0000 0000 0000 0100 - 4
	printf("%u\n", a << 3);//0000 0000 0000 0000 0000 0000 0000 1000 - 8
	//逻辑右移
	unsigned int b = 100;  //0000 0000 0000 0000 0000 0000 0110 0100 - 100
	printf("%u\n", b >> 1);//0000 0000 0000 0000 0000 0000 0011 0010 - 50
	printf("%u\n", b >> 2);//0000 0000 0000 0000 0000 0000 0001 1001 - 25
	printf("%u\n", b >> 3);//0000 0000 0000 0000 0000 0000 0000 1100 - 12
	//算术右移,最高位补符号位1, 虽然移出了最低位1,但是补得还是1
	int c = -1;            //1111 1111 1111 1111 1111 1111 1111 1111 - -1
	printf("%d\n", c >> 1);//1111 1111 1111 1111 1111 1111 1111 1111 - -1
	printf("%d\n", c >> 2);//1111 1111 1111 1111 1111 1111 1111 1111 - -1
	printf("%d\n", c >> 3);//1111 1111 1111 1111 1111 1111 1111 1111 - -1
	//是算术右移,还是逻辑右移?最高位补0,为何?
	unsigned int d = -1;   //1111 1111 1111 1111 1111 1111 1111 1111 
	printf("%d\n", d >> 1);//0111 1111 1111 1111 1111 1111 1111 1111 - 2147483647
	printf("%d\n", d >> 2);//0011 1111 1111 1111 1111 1111 1111 1111 - 1073741823
	printf("%d\n", d >> 3);//0001 1111 1111 1111 1111 1111 1111 1111 - 536870911
	return 0;
}

结论:

        左移,无脑补0。

        右移,先判定是算术右移还是逻辑右移,判定依据:看自身类型,和变量的内容无关。

        判定了是算术,还是逻辑,才能决定最高位补什么。

如何理解"丢弃"

'<<' 和 '>>' 都是计算,都要在CPU中进行,可是参与移动的变量,是在内存中的。 所以需要先把数据移动到CPU内寄存器中,在进行移动。 那么,在实际移动的过程中,是在寄存器中进行的,即大小固定的单位内。那么,左移右移一定会有位置跑到"外边"的情况。

一个问题

#include<stdio.h>
int main()
{
	int a = 10;
	a << 1; //有没有影响a本身的值,为什么?怎么样做能影响a的值
	printf("%d\n", a);
	return 0;
}

learn_C_deep_11 (深刻理解整形提升、左移和右移规则、花括号、++和--操作、表达式匹配:贪心算法)

 0x01<<2+3 的值是多少

#include <stdio.h>
int main()
{
	//0x01:0000 0000 0000 0000 0000 0000 0000 0001
	printf("%d\n", 0x01 << 2 + 3);//32
	printf("%d\n", 0x01 << (2 + 3));//32
	printf("%d\n", (0x01 << 2) + 3);//7
	return 0;
}

        这是一个C语言程序,其中定义了一个main函数,函数中执行了三个printf语句,分别输出了三个表达式的结果。

        这三个表达式的意义如下:

1. 0x01 << 2 + 3

        这个表达式中,先进行加法运算2+3,结果为5,然后再对0x01(二进制为0000 0001)进行左移5位操作,即在二进制的右侧补5个0,得到的结果为0010 0000,即十进制的32。

2. 0x01 << (2 + 3)

        这个表达式中,由于加法运算的优先级比位运算低,所以先执行括号内的加法运算,得到的结果为5。然后再对0x01进行左移5位操作,得到的结果为0010 0000,即十进制的32。

3. (0x01 << 2) + 3

        这个表达式中,先对0x01进行左移2位操作,得到的结果为0000 0100,即十进制的4。然后再将得到的结果与3进行加法运算,得到的结果为7。

        综上所述,这个程序的输出结果为:32     32     7

花括号

        在C语言中,花括号是用来表示代码块的。一个代码块包含一组语句,可以作为一个整体进行控制。花括号通常用于控制语句(如if、for、while等)的语法结构,以及函数、结构体等作用域的定义中。 在代码中,花括号用于将一组语句组合成一个代码块。花括号中的语句可以被认为是一个整体,可以作为一个单元进行控制。

//别这么写
#include <stdio.h>
int main()
{
	char a[] = { "abcde" };
	printf("%d\n", sizeof(a));

	char a[]{ = "abcde"};//error
	printf("%d\n", sizeof(a));

	char a[10]{ = "abcde" };//error
	printf("%d\n", sizeof(a));

	return 0;
}

规规矩矩写代码,不能乱写{ }。

++、--操作

#include <stdio.h>
int main()
{
	int a = 10;
	int b = ++a; //前置++, 先自增在使用
	printf("%d, %d\n", a, b); //11,11
	return 0;
}

        程序中的操作主要集中在语句 int b = ++a; 中,这是一个前置++的运算,它的作用是先让a自增1,然后再将自增后的值赋给b,因此,最终a和b的值都变成了11。

#include <stdio.h>
int main()
{
	int a = 10;
	int b = a++; //后置++, 先使用在自增
	printf("%d, %d\n", a, b); //11, 10
	return 0;
}

        程序中的操作主要集中在语句 int b = a++; 中,它是一个后置++运算,它的作用是先将a的值赋给b,然后再执行自增操作,因此,最终a的值为11,而b的值为10。

#include <stdio.h>
int main()
{
	int a = 0xDD;
	//有b接收,那么a的先使用是将a的值(内容),放到b中
	int b = a++; 

	int c = 0xEE;
	//没有接收方,那么"先使用",如何理解?
	c++; 
	return 0;
}

learn_C_deep_11 (深刻理解整形提升、左移和右移规则、花括号、++和--操作、表达式匹配:贪心算法)

        a++完整的含义是先使用,在自增。如果没有变量接收,那么直接自增(或者所谓使用,就是读取进寄存器,然后没有 然后)。 

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

learn_C_deep_11 (深刻理解整形提升、左移和右移规则、花括号、++和--操作、表达式匹配:贪心算法)

        本代码结果不同的原因就是 i 变量自增后有没有影响后面的 i 值。i 是自己自增完后经过加法运算后 i 再自增,还是三次 i 都自增完然后再进行加法操作。

 我们现在来看一下vs下的计算过程

learn_C_deep_11 (深刻理解整形提升、左移和右移规则、花括号、++和--操作、表达式匹配:贪心算法)

本质:是因为上面表达式的"计算路径不唯一"(为什么?编译器识别表达式,是同时加载至寄存器,还是分批加载,完全不确定)导致的。以后,类似这种复杂表达式,我们一律不推荐使用或者编写。

表达式匹配:贪心算法

#include<stdio.h>
int main()
{
	int a = 10;
	int b = 20;
	printf("%d\n", a++++ + b); //自动匹配失败
    //    贪心算法:(a++)++ + b
	int a = 10;
	int b = 20;
	printf("%d\n", a++ + ++b); //自行分离匹配,非常不推荐,不过能看出空格的好处
	return 0;
}

        在这段代码中,我们看到了两个不同的表达式。第一个表达式是 `a++++ + b`,它会自动匹配失败,因为自增运算符只能和一个变量一起使用。由于自增运算符的优先级比加法运算符高,因此编译器会将其解释为 `(a++)++ + b`,这是非法的表达式。因此,编译器会报告错误。

        第二个表达式是 `a++ + ++b`,它虽然能够被编译器解析正确,但这种写法不够清晰,不推荐使用。这个表达式中包含了两个自增运算符,其中一个跟在变量名前面,另一个跟在变量名后面。由于自增运算符的优先级高于加法运算符,编译器会首先对 `++b` 进行自增操作,然后将 `a` 和 `b` 进行加法运算。

        在这两个表达式中,我们都可以看到贪心算法的影子。贪心算法会尽可能地选择当前最优的解决方案,但在这里,由于自增运算符只能和一个变量一起使用,所以编译器只能尽量匹配,直到遇到无法匹配的表达式为止。因此,为了避免这种情况,我们应该尽量避免写出复杂的、不清晰的表达式。文章来源地址https://www.toymoban.com/news/detail-450882.html

到了这里,关于learn_C_deep_11 (深刻理解整形提升、左移和右移规则、花括号、++和--操作、表达式匹配:贪心算法)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • deep learning 代码笔记

    len (X)总是返回第0轴的长度。 What are the shapes of summation outputs along axis 0, 1, and 2? f ( x ) = ||  x||   2 的梯度 自动微分法计算: 因此,梯度是x的单位向量。在x = 0处的梯度在数学上是未定义的,但是自动微分返回零。要小心,在这种情况下可能会出现差异。 默认情况下,最后一

    2024年02月21日
    浏览(44)
  • Deep Learning-学习笔记

    deep learning训练过程 如果对所有层同时训练,时间复杂度会太高;如果每次训练一层,偏差就会逐层传递。这会面临跟上面监督学习中相反的问题,会严重欠拟合(因为深度网络的神经元和参数太多了)。 2006年,hinton提出了在非监督数据上建立多层神经网络的一个有效方法,

    2024年02月12日
    浏览(36)
  • MATLAB Deep learning

    深度学习是一种机器学习,而机器学习是一种人工智能。 机器学习的本质 :机器学习是一种从“数据”中找到“模型”的技术。在这里,数据的字面意思是指文档、音频、图像等信息。这个“模型”是机器学习的最终产物。 机器学习的创建是为了 解决分析模型几乎不可用的

    2024年01月17日
    浏览(130)
  • The Deep Learning AI for Environmental Monitoring——Deep

    作者:禅与计算机程序设计艺术 环境监测是整个经济社会发展的一个重要环节,环境数据是影响经济、金融、社会和政策走向的不可或缺的组成部分。目前,环境监测主要依靠地面站(例如气象台)或者卫星遥感影像获取的数据进行实时监测,其精确度受到数据源和采集技术

    2024年02月08日
    浏览(46)
  • Tips for Deep Learning

    目录 Recipe of Deep Learning  Good Results on Training Data? New activation function Adaptive learning rate Good Results on Testing Data? Early Stopping Regularization Dropout 我们要做的第一件事是,提高model在training set上的正确率,然后要做的事是,提高model在testing set上的正确率。 这一部分主要讲述如何在

    2024年02月05日
    浏览(45)
  • 《Dive into Deep Learning》

    《Dive into Deep Learning》:https://d2l.ai/ Interactive deep learning book with code, math, and discussions Implemented with PyTorch, NumPy/MXNet, JAX, and TensorFlow Adopted at 500 universities from 70 countries 《动手学深度学习》中文版:https://zh.d2l.ai/chapter_preface/index.html 课程安排: https://courses.d2l.ai/zh-v2/

    2024年02月11日
    浏览(48)
  • 《Learning to Reweight Examples for Robust Deep Learning》笔记

    [1] 用 meta-learning 学样本权重,可用于 class imbalance、noisy label 场景。之前对其 (7) 式中 ϵ i , t = 0 epsilon_{i,t}=0 ϵ i , t ​ = 0 ( 对应 Algorithm 1 第 5 句、代码 ex_wts_a = tf.zeros([bsize_a], dtype=tf.float32) )不理解:如果 ϵ epsilon ϵ 已知是 0,那 (4) 式的加权 loss 不是恒为零吗?(5) 式不是

    2024年01月23日
    浏览(94)
  • AIGC实战——深度学习 (Deep Learning, DL)

    深度学习 ( Deep Learning , DL ) 是贯穿所有生成模型 ( Generative Model ) 的共同特征,几乎所有复杂的生成模型都以深度神经网络为核心,深度神经网络能够学习数据结构中的复杂关系,而不需要预先提取数据特征。在本节中,我们将介绍深度学习基本概念,并利用 Keras 构建深度神

    2024年02月08日
    浏览(43)
  • 可信深度学习Trustworthy Deep Learning相关论文

    Survey An Overview of Catastrophic AI Risks. [paper] Connecting the Dots in Trustworthy Artificial Intelligence: From AI Principles, Ethics, and Key Requirements to Responsible AI Systems and Regulation. [paper] A Survey of Trustworthy Federated Learning with Perspectives on Security, Robustness, and Privacy. [paper] Adversarial Machine Learning: A Systemati

    2024年02月13日
    浏览(40)
  • labml.ai Deep Learning Paper Implementations

    labml.ai Deep Learning Paper Implementations github地址:https://github.com/labmlai/annotated_deep_learning_paper_implementations 可视化网站:https://nn.labml.ai/ 来自B站

    2024年02月12日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包