C和C指针小记(八)-操作符、左值右值
1、移位操作符
移位操作符分为左移操作符(<<)和右移操纵符(>>)
对于无符号数:左右位移操作都是逻辑位移
对于有符号数:到底是采用逻辑位移还是算术位移取决于编译器.如果一个出现使用了有符号数的右移操作,它就是不可移植的.
对于左移操作:右边空出来的位数用0补齐.
对于右移操作:如果是逻辑位移,左边移入的位用0填充;如果是算术位移,左边移入的位由原先该值的符号位决定,符号为为1则移入的位均为1,符号为为0则移入的位均为0.
注意:
a << -5;
这种形式的移位由编译器决定.它产生的效果是不可预知的.
2、位操作符
位操作符对它们的操作数的各个位执行与,或,异或,补等逻辑操作.
包括: AND OR XOR, 分别代表 与,或,异或,(补)
对应的操作符是: & | ^ ~
3、位操作的应用
3.1 统计输入字符中的字符个数,单词个数,换行符个数
/*
* 统计输入的字符串中 行数,制表符,字符的个数,注意没有break,因为美出现一次换行符就表示单词个数和字符个数也增加了,每出现一次 空字符或制表符,字符个数也增加了
*/
int ch;
int lines = 0;
int words = 0;
int chars = 0;
while ((ch = getchar()) != EOF) {
switch (ch) {
case '\n':
lines += 1;
case ' ':
case '\t':
words += 1;
default:
chars += 1;
}
}
3.2 把一个整数的某位数置为1
//把value1 的第五位数置为1
int value1 = 5;
printf("value1: %d ",value1);//5 b0101
value1 = value1 | 1 << 5;//把value1 的第五位数置为1
printf("value1: %d\n",value1);//37 b10101
3.3 把一个数的某位数置为0
//把value2 的第5位数置为0
int value2 = 32;
printf("value2: %d ", value2);//32 b10000
value2 = value2 & ~( 1 << 5);
printf("value2: %d\n", value2);//0 b00000
3.4 测试整数的二进制序列某位是否为1
//测试第4位是否为1
int value3 = 15;
printf("value3: %d\n", value3);//15
printf("value3 的第4位为 %d \n",(value3 & 1 << 4));//value3 的第4位为 0
3.5 返回函数参数值中值为1的位的个数
//返回函数参数值中值为1的位的个数
int count_one_bits(unsigned value) {
int ones;
for(ones = 0; value != 0; value >>= 1){
if ((value & 1) != 0) {
ones += 1;
}
}
return ones;
}
4、赋值操作符 =
需要注意的点:
a = x = y +3;
如果x是一个字符型变量,那么 y+3的值就会被截去一段,以便容纳与字符类型的变量中.那么a所赋的值就是被截取后的值.
还有之前提到的:
char ch;
while((ch = getchar()) !=EOF)
因为EOF需要的位数比字符型值所能提供的位数要多,这也是getchar返回一个整型值而不是字符值的原因.然而,把 getchar() 的返回值先存储与ch中将导致它被截断.
然后这个被截断的值被提升位整型并与EFO进行比较.这段存在错误的代码在使用有符号字符集的机器上运行时,如果读取了一个值位\377的字节时,循环将会终止.因为这个值截短再提升之后与EOF相等.当这段代码在使用无符号字符集的机器上运行时,这个循环将永远不会终止.
此外还有复合赋值符, 它可以是程序变得简洁
+= -= *= /= %=
<<= >>= &= ^= |=
5、单目操作符
- ! ++ - & sizeof
- -- + * (类型)
! 逻辑反操作
\ ~ 求补操作
- 产生操作数的负值
+ 产生操作数的值,等于啥都不干
& 产生操作数的地址
* 简介访问,与指针一起使用,用于访问指针所指的值
sizeof 判断它的操作数的类型长度,以字节为单位.操作数可以是个表达式(常常是单个变量),也可以是两边加上括号的类型名.
如:sizeof(int) sizeof x.
注意:sizeof(a = b+1) 并没有向a赋任何值.
() 强制类型转换 (cast),用于显式的把表达式转换为另外的类型.
++
这两个表达式有前缀和后缀形式.一般和赋值操作符一起使用.
6、下标
array[n] 等价于 *(array + (n))
. 和 -> 都是用来访问一个结构的成员的.
如果s是一个结构变量,那么 s.a 就访问s中名叫a的成员.
当你拥有一个指向结构体的指针而不是结构本身,切欲访问它的成员时,就需要使用 -> 操作符,而不是. 操作符.
7、左值和右值
左值就是那些能够出现在赋值符号左边的东西,右值就是那些可以出现在赋值符号右边的东西.
左值可是一个变量,也可以是一个表达式.但大多住表达式都能作为左值.表达式作为左值时,它的含义必须是一个特定的内存位置.
例如:
a = b + 1;// a 就是一个左值
但是 b + 1 = a; // b+1就不能作为一个左值,
int a[30];
a[b + 10] = 0;//这里表达式就是一个左值
再如:
int a, *pi;
pi = &a;
*pi = 20;//这里 *p作为一个间接取值表达式 就是一个左值 它表示pi所指定来需要进行修改的位置.
int c = *pi;//这里 *p 的含义就是提取当前存储与这个位置的值.
C和C指针小记(八)-操作符、左值右值的更多相关文章
- C++ 左值 右值
最近在研究C++ 左值 右值,搬运.收集了一些别人的资料,供自己记录和学习,若以后看到了更好的解释,会继续补充.(打“?”是我自己不明白的地方 ) 参考:<Boost程序库探秘——深度解析C ...
- 左值&右值
一.引子 我们所谓的左值.右值,正确的说法应该是左值表达式.右值表达式. 因为C++的表达式不是左值就是右值. 在C中,左值指的是既能够出现在等号左边也能出现在等号右边的表达式,右值指的则是只能出现在 ...
- c++ 左值右值 函数模板
1.先看一段代码,这就是一种函数模板的用法,但是红色的部分如果把a写成a++或者写成一个常量比如1,都是编译不过的,因为如果是a++的话,实际上首先是取得a的 值0,而0作为一个常量没有地址.写成1也 ...
- C++ 左值与右值 右值引用 引用折叠 => 完美转发
左值与右值 什么是左值?什么是右值? 在C++里没有明确定义.看了几个版本,有名字的是左值,没名字的是右值.能被&取地址的是左值,不能被&取地址的是右值.而且左值与右值可以发生转换. ...
- C++11之右值引用(一):从左值右值到右值引用
C++98中规定了左值和右值的概念,但是一般程序员不需要理解的过于深入,因为对于C++98,左值和右值的划分一般用处不大,但是到了C++11,它的重要性开始显现出来. C++98标准明确规定: 左值是 ...
- C语言几个术语: 数据对象,左值,右值
1. 数据对象 赋值表达式语句的目的是把值存储到内存位置上. 用于存储值的数据存储区域统称为数据对象. 2. 左值 左值是C语言的术语, 用于标识特定数据对象的名称或表达式. 对象指的是实际的数据存储 ...
- i++和++i以及左值,右值
左值(LValue)和右值(RValue)的一个快捷记法是赋值运算,左值是赋值运算左边的值,右值就是右边(=,=废话).例如: int a = 5; a就是左值,5就是右值. 当然,如果真是这么个含义 ...
- C++雾中风景10:聊聊左值,纯右值与将亡值
C++11的版本在类型系统上下了很大的功夫,添加了诸如auto,decltype,move等新的关键词来简化代码的编写与降低阅读代码的难度.为了更好的理解这些新的语义,笔者确定通过几篇文章来简单窥探一 ...
- C++中的左值与右值(二)
以前以为自己把左值和右值已经弄清楚了,果然发现自己还是太年轻了,下面的这些东西是自己通过在网上拾人牙慧,加上自己的理解写的. 1. 2. 怎么区分左值和右值:知乎大神@顾露的回答. 3. 我们不能直接 ...
随机推荐
- 11g新特性-SQL Plan Management
在11g之前版本,提供了stored outlines(sql概要)特性来保存sql的执行计划. 在11g中,引入了一个新的特性sql计划管理(sql plan management)特性来保存sql ...
- 第三部分:Android 应用程序接口指南---第四节:动画和图形---第一章 属性动画及动画与图形概述
第1章 属性动画及动画与图形概述 Android提供了一系列强大的API来把动画加到UI元素中,以及绘制自定义的2D和3D图像中去.下面的几节将综述这些可用的API以及系统的功能,同时帮你做出最优的选 ...
- JAVA和JAVAC 命令行
转自:http://www.blogjava.net/pdw2009/archive/2008/06/12/207413.html?opt=admin javac和java命令行中的-classpat ...
- 【Linux高级驱动】linux设备驱动模型之平台设备驱动机制
[1:引言: linux字符设备驱动的基本编程流程] 1.实现模块加载函数 a.申请主设备号 register_chrdev(major,name,file_operations); b.创 ...
- C++ 智能指针三
/* 智能指针shared_ptr注意点 */ #include <iostream> #include <string> #include <memory> // ...
- 解决com.mysql.jdbc.PacketTooBigException: Packet for query is too large
在做查询数据库操作时,报了以上错误,还有out of memery heap hacp ,原因是MySQL的max_allowed_packet设置过小引起的,我一开始设置的是1M,后来改为了20M ...
- Python内置类型——list
list(列表)是Python内置的可变序列(Sequence)类型,list的对象的方法也都是就地(in-place)更改调用这些方法的列表对象, List的一些细节 可以直接为list的某个下标赋 ...
- .Net MVC Cache 缓存技术总结
一.细说 ASP.NET Cache 及其高级用法 二..Net环境下的缓存技术介绍 (转) 三.asp.net中缓存的使用介绍一 四.HttpContext.Current.Cache 过期时间
- Spark学习笔记——构建分类模型
Spark中常见的三种分类模型:线性模型.决策树和朴素贝叶斯模型. 线性模型,简单而且相对容易扩展到非常大的数据集:线性模型又可以分成:1.逻辑回归:2.线性支持向量机 决策树是一个强大的非线性技术, ...
- HTTP Status 500 - Could not open Hibernate Session for transaction;
错误原因: mysql数据库没有连接上 我们来启动mysql 方法1: 管理员身份运行 cmd 输入: net start mysql 方法2: Windows + R 运行 services.ms ...