返回信息流没时间整理,就随手发发:
运算符&和*
这里&是取地址运算符,*是...书上叫做“间接运算符”。&a的运算结果是一个指针,指针的类型是a的类型加个*,指针所指向的类型是a的类型,指针所指向的地址嘛,那就是a的地址。*p的运算结果就五花八门了。总之*p的结果是p所指向的东西,这个东西有这些特点:它的类型是p指向的类型,它所占用的地址是p所指向的地址。
例五:
int a=12;
int b;
int *p;
int **ptr;
p=&a;//&a的结果是一个指针,类型是int*,指向的类型是int,指向的地址是a的地址。
*p=24;//*p的结果,在这里它的类型是int,它所占用的地址是p所指向的地址,显然,*p就是变量a。
ptr=&p;//&p的结果是个指针,该指针的类型是p的类型加个*,在这里是int **。该指针所指向的类型是p的类型,这里是int*。该指针所指向的地址就是指针p自己的地址。
*ptr=&b;//*ptr是个指针,&b的结果也是个指针,且这两个指针的类型和所指向的类型是一样的,所以用&b来给*ptr赋值就是毫无问题的了。
**ptr=34;//*ptr的结果是ptr所指向的东西,在这里是一个指针,对这个指针再做一次*运算,结果就是一个int类型的变量。
这是一条镜像帖。来源:北邮人论坛 / sse / #5781同步于 2008/3/26
该镜像源已超过 30 天没有更新,可能在源站已被删除。
SSE机器人发帖
写完java,不觉有些miss c,发篇关于c细节的帖子,希望有用
Goldfather
2008/3/26镜像同步14 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
按位异或运算符^
逻辑运算均是按位进行操作,真值表如下:
AND (位与&) OR ( 位或| ) XOR ( 位异或^ )
1 & 1 = 1
1 & 0 = 0
0 & 1 = 0
0 & 0 = 0
1 | 1 = 1
1 | 0 = 1
0 | 1 = 1
0 | 0 = 0
1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0
例如: 10100001^00010001=10110000
0^0=0,0^1=1 0异或任何数=任何数
1^0=1,1^1=0 1异或任何数-任何数取反
任何数异或自己=把自己置0
(1)按位异或可以用来使某些特定的位翻转,如对数10100001的第2位和第3位翻转,可以将数与00000110进行按位异或运算。
10100001^00000110=10100111 //1010 0001 ^ 0x06 = 1010 0001 ^ 6
(2)通过按位异或运算,可以实现两个值的交换,而不必使用临时变量。例如交换两个整数a,b的值,可通过下列语句实现:
a=10100001,b=00000110
a=a^b; //a=10100111
b=b^a; //b=10100001
a=a^b; //a=00000110
(3) 按位异或满足交换律和接合律
a^b = b^a
a^b^c = a^(b^c)
(4) a^a = 00000000000000 (全是零)
(5) a^ 全是零 = a
利用 (3)(4)(5) 可以证明 (2)
...................
操作符
电脑的基本是数字,那么电脑的所有操作都是改变数字,因此很正常地C++提供了操作数字的一些基本操作,称作操作符(Operator),如:+ - * / 等。任何操作符都要返回一个数字,称为操作符的返回值,因此操作符就是操作数字并返回数字的符号。作为一般性地分类,按操作符同时作用的数字个数分为一元、二元和三元操作符。
一元操作符有:
+ 其后接数字,原封不动地返回后接的数字。如: +4.4f的返回值是4.4;+-9.3f的返回值是-9.3。完全是出于语义的需要,如表示此数为正数。
- 其后接数字,将后接的数字的符号取反。如: -34.4f的返回值是-34.4;-(-54)的返回值是54。用于表示负数。
! 其后接数字,逻辑取反后接的数字。逻辑值就是“真”或“假”,为了用数字表示逻辑值,在 C++中规定,非零值即为逻辑真,而零则为逻辑假。因此3、43.4、'A'都表示逻辑真,而0则表示逻辑假。逻辑值被应用于后续的判断及循环语句中。而逻辑取反就是先判断“!”后面接的数字是逻辑真还是逻辑假,然后再将相应值取反。如:
!5的返回值是0,因为先由5非零而知是逻辑真,然后取反得逻辑假,故最后返回0。
!!345.4的返回值是1,先因345.4非零得逻辑真,取反后得逻辑假,再取反得逻辑真。虽然只要非零就是逻辑真,但作为编译器返回的逻辑真,其一律使用1来代表逻辑真。
~ 其后接数字,取反后接的数字。取反是逻辑中定义的操作,不能应用于数字。为了对数字应用取反操作,电脑中将数字用二进制表示,然后对数字的每一位进行取反操作(因为二进制数的每一位都只能为1或0,正好符合逻辑的真和假)。如~123的返回值就为-124。先将123转成二进制数01111011,然后各位取反得10000100,最后得-124。
这里的问题就是为什么是8位而不是16位二进制数。因为123小于128,被定位为char类型,故为8位(关于char是什么将下篇介绍)。如果是~123ul,则返回值为4294967172。
为什么要有数字取反这个操作?因为CPU提供了这样的指令。并且其还有着很不错且很重要的应用,后面将介绍。
关于其他的一元操作符将在后续文章中陆续提到(但不一定全部提到)。
二元操作符有:
+
-
*
/
% 其前后各接一数字,返回两数字之和、差、积、商、余数。如:
34+4.4f的返回值是38.4;3+-9.3f的返回值是-6.3。
34-4的返回值是30;5-234的返回值是-229。
3*2的返回值是6;10/3的返回值是3。
10%3的返回值是1;20%7的返回值是6。
&&
|| 其前后各接一逻辑值,返回两逻辑值之“与”运算逻辑值和“或”运算逻辑值。如:
'A'&&34.3f的返回值是逻辑真,为1;34&&0的返回值是逻辑假,为0。
0||'B'的返回值是逻辑真,为 1;0||0的返回值是逻辑假,为0。
&
|
^ 其前后各接一数字,返回两数字之“与”运算、“或”运算、“异或”运算值。如前面所说,先将两侧的数字转成二进制数,然后对各位进行与、或、异或操作。如:
4&6的返回值是4,4转为00000100,6转为00000110各位相与得,00000100,为4。
4|6的返回值是6,4转为00000100,6转为00000110各位相或得,00000110,为6。
4^6的返回值是2,4转为00000100,6转为00000110各位相异或得,00000010,为2。
>
<
==
>=
<=
!= 其前后各接一数字,根据两数字是否大于、小于、等于、大于等于、小于等于及不等于而返回相应的逻辑值。如:
34>34的返回值是0,为逻辑假;32<345的返回值为1,为逻辑真。
23>=23和23>=14的返回值都是1,为逻辑真;54<=4的返回值为0,为逻辑假。
56==6的返回值是0,为逻辑假;45==45的返回值是1,为逻辑真。
5!=5的返回值是0,为逻辑假;5!=35的返回值是真,为逻辑真。
>>
<< 其前后各接一数字,将左侧数字右移或左移右侧数字指定的位数。与前面的 ~、&、|等操作一样,之所以要提供左移、右移操作主要是因为CPU提供了这些指令,主要用于编一些基于二进制数的算法。
<<将左侧的数字转成二进制数,然后将各位向左移动右侧数值的位数,如:4,转为00000100,左移2位,则变成00010000,得16。
>>与<<一样,只不过是向右移动罢了。如:6,转为00000110,右移1位,变成00000011,得3。如果移2位,则有一位超出,将截断,则6>>2的返回值就是00000001,为1。
左移和右移有什么用?用于一些基于二进制数的算法,不过还可以顺便作为一个简单的优化手段。考虑十进制数3524,我们将它左移2位,变成352400,比原数扩大了100倍,准确的说应该是扩大了10的2次方倍。如果将3524右移2位,变成35,相当于原数除以100的商。
同样,前面4>>2,等效于4/4的商;32>>3相当于32/8,即相当于32除以2的3次方的商。而4<<2等效于4*4,相当于4乘以2的2次方。因此左移和右移相当于乘法和除法,只不过只能是乘或除相应进制数的次方罢了,但它的运行速度却远远高于乘法和除法,因此说它是一种简单的优化手段。
, 其前后各接一数字,简单的返回其右侧的数字。如:
34.45f,54的返回值是54;-324,4545f的返回值是4545f。
那它到底有什么用?用于将多个数字整和成一个数字,在《C++从零开始(四)》中将进一步说明。
关于其他的二元操作符将在后续文章中陆续提到(但不一定全部提到)。
三元操作符只有一个,为?:,其格式为:<数字1>?<数字2>:<数字3>。它的返回值为:如果<数字1>是逻辑真,返回<数字2>,否则返回<数字3>。如:
34?4:2的返回值就是4,因为34非零,为逻辑真,返回4。而0?4:2的返回值就是2,因为0为逻辑假,返回2。
调用规则
调用规则指函数的参数如何传递,返回值如何传递,以及上述的函数名标识符如何修饰。其并不属于语言级的内容,因为其表示编译器如何实现函数,而关于如何实现,各编译器都有自己的处理方式。在VC中,其定义了三个类型修饰符用以告知编译器如何实现函数,分别为:__cdecl、__stdcall和__fastcall。三种各有不同的参数、函数返回值传递方式及函数名修饰方式,后面说明异常时,在说明了函数的具体实现方式后再一一解释。由于它们是类型修饰符,则可如下修饰函数:
void *__stdcall ABC( long ), __fastcall DE(), *( __stdcall *pAB )( long ) = &ABC;
void ( __fastcall *pDE )() = DE;
指针和函数的关系
可以把一个指针声明成为一个指向函数的指针。
int fun1(char*,int);
int (*pfun1)(char*,int);
pfun1=fun1;
....
....
int a=(*pfun1)("abcdefg",7);//通过函数指针调用函数。
可以把指针作为函数的形参。在函数调用语句中,可以用指针表达式来作为实参。
例十三:
int fun(char*);
int a;
char str[]="abcdefghijklmn";
a=fun(str);
...
...
int fun(char*s)
{
int num=0;
for(int i=0;i {
num+=*s;s++;
}
return num;
}
这个例子中的函数fun统计一个字符串中各个字符的ASCII码值之和。前面说了,数组的名字也是一个指针。在函数调用中,当把str作为实参传递给形参s后,实际是把str的值传递给了s,s所指向的地址就和str所指向的地址一致,但是str和s各自占用各自的存储空间。在函数体内对s进行自加1运算,并不意味着同时对str进行了自加1运算。
这孩子是我寝室的,没看好他让他跑出来发帖,让汪学长见笑了。。。。。
【 在 shuishou913 (shuishou913) 的大作中提到: 】
: 这孩子谁啊,他没事吧?
学长你好,我就是lz,没事,就是写完java后看到些关于c的好资料,一时手痒发上来分享而已,见笑了...
【 在 shuishou913 (shuishou913) 的大作中提到: 】
: 这孩子谁啊,他没事吧?
int fun(char*s)
{
int num=0;
for(int i=0;i {
num+=*s;s++;
}
return num;
}
--------------------------------------
for(int i=0;i {
这啥意思啊?
另外c里不能直接在for循环里声明变量