赋值操作符
int a,b,c;
a = b = c = 10;
赋值操作符是从右向左进行赋值的,因此c先赋值,然后将c的值赋予b,以此类推。
a = 10;
c = a + (b = a + 10);
先给b 赋值20,然后进行计算,得到 c 等于30
#include <stdio.h>
int main(void)
{
int a, b;
a = 5 ;
b = a + (a = a + 10);
printf("The a value is %d\nThe b value is %d\n",a,b);
return 0;
}
所以这个时候也要注意,a值的变化,结果为:
The a value is 15
The b value is 30
我们规定变量作为左值(不能为表达式),常数作为右值
因此下面式子是错误的
10 = a; /* Illegal. */
a+b = 20; /* Illegal. */
int a;
float b;
b = a = 5.5 ;
因为a为整型,在a赋值的时候,它会强制等于5
此时b值为5.00000
在此有一个地方需要注意:
-= 与 =-
a -= 1 的意思是 a = a - 1
a =-1的意思是a = -1
因此我建议在写赋值的时候,一定要有空格,方便区分。
算数符号
算术符号主要是: + - * \ %
++ 与 – 操作符
int a = 4;
a++; /* Equivalent to a = a+1; */
++a; /* Equivalent to a = a+1; */
(a+10)++; /* Illegal. */
经常拿来区分的他们在变量的位置问题:
int a = 4, b;
b = a++;
++在a后面,那么就说明先进行其他操作,最后执行++操作
因此b = 4, a = 5
int a = 4, b;
b = ++a;
++在a前面,那么就说明先进行执行++操作,然后其他操作
因此b = 5, a = 5
需要注意的是,只要++或者–在当前的语句执行完毕,那么这个操作就算完成了,也就是说赋值完成。
int a = 4;
++a; // 或者是 a++;
printf("a value is %d\n",a);
打印的结果都是:
a value is 5
一个相对比较复杂的例子:
#include <stdio.h>
int main(void)
{
int a = 3;
printf("%d\n", (++a) - (a--) + (--a));
return 0;
}
结果为 2
首先运算顺序是,从右往左,但是都有括号,因此要先计算括号内的数值
(++a) 式子值为 4, a为4
(a–) 式子值为 4,a为3
(–a) 式子值为 2,a为2
然后将值带入: 4 - 4 + 2 = 2
考虑如果没有括号将会如何,答案是不变
因为++,–的优先级比()都高,有没有()是没有变化的
关系运算符
包括 > >= < <= == 和 !=, 这些关系运算符的结果只有两个0 和 1, 0 为假,1 为真。
if(a > 10), 当a = 11时,这个式子成立,得到的结果就是
逗号操作符
逗号的结合律,是从左到右的
#include <stdio.h>
int main(void)
{
int a, b, c = 0;
a = (b = 20, b = b+30, b++);
printf("%d %d\n", a, b);
if(a,b,c)
printf("One\n");
return 0;
}
b = 20, b = b+30, b++ => 先赋值,再计算b=50,在b++
if(a,b,c)这个地方编译器会有警告提示,根据逗号的结合律,事实上只有c参与判断,a,b虽然读取但是,以最后一个变量为主。
因此结果为:
50 51
sizeof操作符
sizeof是用来计算特定变量,常量或者表达式存储值。它的结果是一个size_t类型,这个类型实际上是一个无符号整型值。人们通常使用%d,但是更安全的办法是使用%lu
#include <stdio.h>
int main(void)
{
char c;
int i;
double d;
printf("%lu %lu %lu\n", sizeof(c), sizeof(i), sizeof(d));
printf("%lu %lu %lu\n", sizeof(c+c), sizeof(i+c), sizeof(i+d));
return 0;
}
结果为:
1 4 8
4 4 8
sizeof最经常的用法是在分配内存时使用:
malloc(100*sizeof(int));
枚举类型 enum
声明格式:
enum tag {enumeration_list};
我们也可以使用define来定义别名,但是使用enum更方便
#define MON 1
#define TUE 2
#define WED 3
#define THU 4
#define FRI 5
#define SAT 6
#define SUN 7
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
枚举类型的值是从第一个元素开始累加的,第一个元素默认为0,第二个为1
我们也可以手动设置某个元素的数值,然后下一个元素,从上一个元素数值上加1,依次累加。
声明一个枚举类型,并不可以直接使用,需要定义一下,如下:
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY day;
定义了day作为枚举DAY类型。
类似于 int 你是不可以直接使用的,需要定一个变量 i。 int i;
#include<stdio.h>
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
int main()
{
enum DAY day;
day = WED;
printf("%d",day);
return 0;
}
void test(enum codes c); instead of void test(int c);
使用第一个会方便我们阅读和理解,我们知道参数为一系列的数值。
通常来说,我们使用#define来定义一些,彼此不相关的,或者是不能用整数来表示的。
位操作符
&操作符:
此操作符是双操作符,即AND。
&的运算规则是:只有当前位的都为1的时候,取1,其他都取0
通常我们是用来取低位的数值
int a = 19;
a = a & 3;
| 操作符
此操作符是双操作符,即OR。
&的运算规则是:只要其中一位为1的时候,取1,其他都取0
^操作符
此操作符是双操作符,即XOR。
|的运算规则是:只要双方不同,取1,其他都取0
~操作符
此操作符是单操作符,即NOT。
~的运算规则是:为0位,取1,为1位,取0
shift操作符
>> 表示位的右移,<<表示位的左移。
位移的值是有范围的的,比如一个整型是32bit,那么它的位移范围就是0~31,32或者-1都是错误的范围。
unsigned int a, b = 35;
a = b >> 2;
35 is 00100011 向右位移2位,就得到001000。
a = 8,b = 35
因为b只是发生了位移,并没有对b的值进行修改。
unsigned int a, b = 35;
a = b << 3;
00100011 向左位移3位,就得到00100011000。
实际上,无符号int是有32位,我们只是没有必要把所有的0都写出来而已。
在无符号int的数值范围内,发生左移就是扩大2^n倍
int a = 1;
a <<= 8;
表示位移并赋值。
位移操作一定要注意值类型问题
unsigned char a = 8;
a <<= 4;
结果为:
128
char a = 8;
a <<= 4;
结果为:
-128