- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章一篇文章带你了解C语言操作符知识由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
我们在初始C语言已经大致了解了操作符,我们今天一起详细解剖操作符.
。
C语言操作符很多,但大致进行分类后,有以下几种操作符 。
//算数操作符+ - * / %//移位操作符<< >>//位操作符& |//赋值操作符= += -= *= /= ...//单目操作符sizeof() ! ++ -- & * //关系操作符> >= < <= ==//逻辑操作符&& ||//条件操作符?://逗号表达式,//其他操作符[] () -> . ...
算数操作符再常见不过, 。
加减乘除,取余.
+ - * /操作符和我们数学上的一样.
值得注意的是 。
/ 。
int c=10/3; c=10.0/3; c=10/3.0; //c结果为3 (double)c=10.0/3; //能计算出小数值
C语言中,/需要至少一个操作数为浮点数,才能使结果为浮点数,并且记得存在浮点数中.
%求余(取模)操作符 。
只能计算两个整型之间的结果,结果也为整型.
这里说的移位,指的是移动二进制位.
有左移,右移操作符.
<<左移操作符 。
向左移动二进制位 。
可以看到二进制左移后,a<<1是a的2倍,所以我们可以知道,左移一位,扩大2倍.
左移n位扩大2^n倍.
>>右移操作符 。
可想而知,右移操作符,也与左移效果类似,二进制位向右移动一位.
右边的二进制丢弃,右边的二进制位,并不是添像左移操作符一样添零,需要分情况讨论.
移位又分为算数移位和逻辑移位.
算数移位就是右移时,左边添加那一位是需要看二进制的符号位,添加。添加的哪一位和符号位相同.
逻辑移位就是不管左移还是右移操作,添加哪一位都是添0.
但我们需要移动一个负数时,显然逻辑移位会改变原数值得正负.
所以在一般的编译器下都采用算数移位.
可以看到右移操作原来的值缩小了2^n倍.
注意:左移和右移都要考虑移位后是否会溢出.
移位操作是针对移动正数位, 。
a>>-1这样移位错误,C语言未定义.
位操作,有&(按位与) , |(按位或),^(按位异或)~(按位取反).
位操作符顾名思义,是针对二进制位的操作,有两个操作数进行,二进制位进行操作运算.
这里我们的二进制位都是指的补码,因为一个数以补码的形式存放在内存中.
// 00000000 00000000 00000000 00100010// 00000000 00000000 00000000 11010110// & 00000000 00000000 00000000 00000010 // | 00000000 00000000 00000000 11110110// ^ 00000000 00000000 00000000 11110100
位操作符 | 作用 |
---|---|
& | 两操作数二进制位都为真(1)结果为真(1)否者为假(0) |
| | 两操作数二进制位为假(0)结果为假(0)否者为真(1) |
^ | 一真(1)一假(0)结果为真(1),否者为假(0) |
~ | 二进制位按位取反,1变0,0变1 |
//尝试写一下这个代码include <stdio.h>int main(){ int num1 = 1; //00000000 00000000 00000000 00000001 int num2 = 2; //00000000 00000000 00000000 00000010 num1 & num2; // 00000000 00000000 00000000 00000000 num1 | num2; // 00000000 00000000 00000000 00000011 num1 ^ num2; // 00000000 00000000 00000000 00000011 return 0;}
不创建新的变量,实现两个变量的交换.
//方法一#include<stdio.h>int main(){int a=3; // 00000000 00000000 00000000 00000011int b=5; // 00000000 00000000 00000000 00000101a=a^b; // 00000000 00000000 00000000 00000110b=a^b; // 00000000 00000000 00000000 00000011a=a^b; // 00000000 00000000 00000000 00000101}
有趣的一道代码,利用^按位异或实现了两数的交换.
^异或操作符的性质 。
a^a=0,
a^0=a,
经常利用这两条性质解题,写出优秀的代码! 。
//方法二#include<stdio.h>int main(){int a=3;int b=5;a=a+b; //a=8b=a-b; // b=3a=a-b; // a=5}
求一个整数存储在内存中二进制1的个数 。
//方法一#include<stdio.h>int main(){int n=10;int count=0;while(n){ if(n%2==1) { count++; } n>>=1;}printf("输入二进制位1的个数:%d",count);}
思考上面的代码是否存在问题 。
当n为负数时?
可以看到程序将会一直死循环下去.
我们优化一下! 。
//方法二#include<stdio.h>int main(){ int i=0; int count=0; int num=-3; for(i=0;i<32;i++) { if((num>>i)&1==1) //移位并且判断最后一位是否为1 count++; } return 0;}
每次都要进行32次循环,我们是否可以再次优化一下! 。
//方法三#include <stdio.h>int main(){ int num = -1; // 10000000 00000000 00000000 00000001 //补码 11111111 11111111 11111111 11111111 int i = 0; int count = 0;//计数 while(num) { count++; num = num&(num-1);//丢弃最后一位1 } printf("二进制中1的个数 = %d\n",count); return 0;}
上面这个代码是不是很神奇,一般人想不到,这就是代码的魅力! 。
赋值操作符,我们再熟悉不过了.
我们可以通过赋值操作符,将一个变量改变成你想要的值! 。
#include<stdio.h>int main(){ int weight=180; weight=125; //不满意可以改变 //连续赋值 int a=13,b=0,c=0; a=b=c=6; //连续赋值操作缺点不易调试}
+= -= *= /= %= … 。
可以看到很多复合赋值操作符 。
a+=2; ===> a=a+2; a*3; ===> a=a*3; //其他运算符一个道理 ....
这边是复合赋值操作符,使用起来很简单,也很方便! 。
//单目操作符就是只有一个操作数的操作符!+ - ! sizeof() ++ -- ~ * (类型)
+ - 。
这里的+ -都是单目操作符,并不是算数操作符中的+-.
a=-5; //-5这里的-指的是单目操作符! b=+5; //+5 +可以省略!
! 逻辑反操作符 。
while(a!=0) //这里就是!逻辑反操作符{ count++; //a不为0count++;}while(!a){count++; //a为0count++;}
sizeof 。
是否感到很诧异,sizeof居然是操作符! 。
sizeof是比较特殊的一个操作符,并不是函数! 。
我们知道sizeof可以计算一个变量和类型的所占空间内存大小! 。
int main(){ int a = -10; int* p = NULL; printf("%d\n", !2); printf("%d\n", !0); a = -a; p = &a; printf("%d\n", sizeof(a)); printf("%d\n", sizeof(int)); printf("%d\n", sizeof a); //这样写行不行? printf("%d\n", sizeof int);//这样写行不行? return 0;}
可以看到当sizeof计算一个类型时,不添加括号,就会报错,然而计算一个变量的大小时却可以省略括号! 。
总结:sizeof计算类型所占内存大小时,括号不可省略。sizeof(类型),计算变量所占内存大小时,sizeof(变量),sizeof变量 。
将错误更改一下,看一下运行结果! 。
sizeof和数组 。
我们知道sizeof可以计算变量的空间大小,所以我们经常通过sizeof计算一个数组的元素个数! 。
公式:sizeof(数组)/sizeof(数组的一个元素) 。
#include <stdio.h>void test1(int arr[]){ printf("%d\n", sizeof(arr));//(2)}void test2(char ch[]){ printf("%d\n", sizeof(ch));//(4)}int main(){ int arr[10] = {0}; char ch[10] = {0}; printf("%d\n", sizeof(arr));//(1) printf("%d\n", sizeof(ch));//(3) test1(arr); test2(ch); return 0;}
问: (1)、(2)两个地方分别输出多少? (3)、(4)两个地方分别输出多少?
我们先通过自己计算一下! 。
计算结果! 。
(1)40 (2) 40 (3)10 (4) 10 。
而运行结果! 。
可以看到,运行结果并不是那样! 。
我们在思考一下这个结果,为啥结果会是4?
我们明明是将数组,直接传参过去 ,而通过sizeof计算的内存大小却不是,难道我们只传参了一个地址过去?
我们调试一下,发现就是假设的这样,数组传参并没有将整个数组传参过去,而是传参了一个指针! 。
而我们在x86也就是32位平台下,指针所占内存空间大小为4个字节.
++ -- 。
//前置++和--: #include <stdio.h> int main() { int a = 10; int x = ++a; //先对a进行自增,然后对使用a,也就是表达式的值是a自增之后的值。x为11。 int y = --a; //先对a进行自减,然后对使用a,也就是表达式的值是a自减之后的值。y为10; return 0; } //后置++和-- #include <stdio.h> int main() { int a = 10; int x = a++; //先对a先使用,再增加,这样x的值是10;之后a变成11; int y = a--; //先对a先使用,再自减,这样y的值是11;之后a变成10; return 0; }
总结: 前置++,--先进行自加操作,再使用! 。
后置++,--先使用再进行自加操作! 。
> >= < <= == (判断是否等于) !=(判断不等于) 。
这些这是基本的关系操作符! 。
我们已经很常见了,我们看一下关系操作符的运行结果! 。
可以看到,当判断结果为真是,vs用1代表真,用0代表假.
注意:我们在测试,结果是否相等时,用==而不是赋值操作符=.
逻辑操作符,有逻辑与&&,逻辑或|| 。
当我们要测试两个表达式结果时,如果要同时满足,使用逻辑与&&只需满足其中一个表达式结果时使用逻辑或|| 。
我们要区分逻辑操作符和位操作符按位与&,按位或|区别! 。
#include<stdio.h>int main(){ int a=3;//00000000 00000000 00000000 00000011 int b=1;//00000000 00000000 00000000 00000001 printf("%d\n",a&b); printf("%d\n",a|b); printf("%d\n",a&&b); printf("%d\n",a||b); return 0;}
位操作符和逻辑操作符截然不同,一个是对整数的二进制进行操作,另一个是对表达式的结果进行判断! 。
&& 只有当两个表达式结果同时为真,结果才为真! 。
|| 只有当两个表达式结果同时为假,结果才为假! 。
逻辑表达式的特性! 。
#include<stdio.h>int main(){int a=3,b=5,c=6,i=0;i=a++&&++b;printf("%d %d\n",a,b);i=a++||++b;printf("%d %d\n",a,b);return 0;}
我们可以看到,逻辑或||第二个表达式,并没有执行.
这是为什么呢! 。
总结: 逻辑与&&当执行到表达式结果为假,便停止执行,后面的表达式! 。
逻辑或||当执行到表达式结果为真,便停止执行后面的表达式! 。
这就是我们常说的逻辑短路特点! 。
exp1 ? exp2 : exp3 。
条件操作符通常由3个表达式构成!又叫(三目操作符)! 。
如果exp1表达式结果为真,执行exp2,否者执行exp3 。
可以看到与我们的判断语句if类似! 。
#include<stdio.h>int main(){ int a=5,b=3,max=0; //if判断语句求最大值 if(a>b) { max=a; } else { max=b; } //条件表达式 a>b?max=a:max=b;return 0;}
可以看到条件表达式的优点,可以大大的简化代码! 。
exp1,exp2,exp3...expN 。
表达式之间用,分隔开,这就是逗号表达式.
表达式特点 。
#include<stdio.h>int main(){ int a=2,b=3,c=5; int i=(a++,b++,c); printf("a=%d b=%d c=%d i=%d",a,b,c,i);return 0;}
可以看到表达式i=(a++,b++,c);结果i=5也就是最后一个表达式c的值.
逗号表达式运算特点:
表达式从左往右依次计算,最后一个表达式的值,便是整个逗号表达式结果的值! 。
[]下标引用操作符 ()函数调用操作符 . ->结构成员访问操作符 。
[]下标引用操作符 。
操作数:一个数组名+一个索引值 。
int arr[10];//创建数组 arr[9] = 10;//实用下标引用操作符。 // [ ]的两个操作数是arr和9。
既然是两个操作数,那么两个操作数可以交换位置吗?
可以看到arr[9]等价9[arr] 。
但是我们并不介意用9[arr] 。
()函数调用操作符 。
( ) 函数调用操作符 接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数.
#include <stdio.h> void test1() { printf("hehe\n"); } void test2(const char *str) { printf("%s\n", str); } int main() { test1();//实用()作为函数调用操作符。 test2("hello bit.");//实用()作为函数调用操作符。 return 0; }
. :结构体.成员名 ->:结构体指针->成员名 。
#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;}
。
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我的更多内容! 。
原文链接:https://blog.csdn.net/weixin_52345071/article/details/120214036 。
最后此篇关于一篇文章带你了解C语言操作符知识的文章就讲到这里了,如果你想了解更多关于一篇文章带你了解C语言操作符知识的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在尝试创建一个 Django 网站,每次在本地主机上运行/articles/api/article 页面时:我都会收到此回溯: Environment: Request Method: GET R
我正在尽最大努力理解开放图谱协议(protocol)中的一切含义阅读 FB page在上面和 OGP Page .这在 FB 和 OGP 的世界中究竟意味着什么: Note that the Open
我的 HTML/CSS 中存在页脚与文章内容重叠的问题。是的,我一直在网上搜索但似乎没有任何效果,我希望你知道它有什么问题。我在这里做了一个codepen: CodePen LINK
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
我可以将变量作为警报显示在函数中,但无法将变量传递给文章。我做错了什么? 我知道“a”保存了正确的信息,因为我已经通过警报显示了它。 我尝试使用以下方式传递变量:placeholderContent.
这个问题已经有答案了: Rails article helper - "a" or "an" (6 个回答) 已关闭 3 年前。 是否有类似 [#pluralize in ActiveSupport]
这个问题已经有答案了: Rails article helper - "a" or "an" (6 个回答) 已关闭 3 年前。 是否有类似 [#pluralize in ActiveSupport]
我有以下型号。 Book has Articles (Article has foreign key to Book) Article has Images (Article has upto #ma
我创建了一个页面,该页面显示了单个 类别下的所有帖子,即如果我单击类别音乐,我将获得与音乐类别相关的所有文章。 但我的目标是创建一个过滤选项,它可以过滤掉某些类别,并且只显示与您过滤的类别相关的所有帖
我使用这样的代码: $query = "SELECT introtext FROM #__content WHERE alias = '$alias'"; $db->setQuery($query);
我在主页上设置了一些特色文章。显示的所有文章似乎都剩下太多填充。我知道足以进入 css 并在 layout.css 上编辑 .itembody 的填充或边距,但似乎没有任何改变。我希望我的文章通过模块
ORM 中存储文章及其修订的最佳实践是什么?当我自己用SQL存储时,我曾经有以下结构: articles [id, parent_id, name, text] 通过parent_id,我可以轻松识
我的 HTML : Interest About Interest
我正在用jade构建一个nodejs、express、mongodb博客。 我的文件夹结构是:项目/ 模块/ 观点/ 索引.jade 应用程序.js 文章提供者内存.js 文章provider-mon
我的问题比较具体,至少对我来说是这样。具体是因为在做了很多搜索之后我找不到任何有用的东西。因此,正如标题所说,我正在寻找一种算法,它会发现输入中给出的两篇文章是否“匹配”,但不是通常的字符串匹配意义上
关闭。这个问题是off-topic .它目前不接受答案。 9年前关闭。 锁定。这个问题及其答案是locked因为这个问题是题外话,但具有历史意义。它目前不接受新的答案或互动。 我无法弄清楚动态编程的原
我有这个问题。我正在建立一个社交网站,我必须在两栏中创建帖子。父容器是一个部分,元素“post”是样式为 float: left 的文章。我如何让滑到那些较短的下方创建的空白空间的帖子? 最佳答案 c
这里有几个关于文件与数据库的问题,但我仍然不确定使用什么以及为什么在我的案例中应该使用它。 我的网站上有很多 HTML 文章(长度在几百到几千字之间)。在数据库 (MySQL) 中,我有一个没有搜索索
微信公众号文章 Semantic Kernel —— LangChain 的替代品? [1] ,它使用的示例代码是Python ,他却发了这么一个疑问: 支持的语言对比(因为 Sem
我想编写一个 polymer 元素来显示一些 WordPress 文章。 http://www.jsv-lippstadt.de/?json=get_category_posts&slug=app
我是一名优秀的程序员,十分优秀!