[1]运算符
1.1 逻辑运算符
&& 逻辑与:全真则真,一假则假
|| 逻辑或:一真则真,全假则假
! 逻辑非:非真则假,非假则真
0为假 1为真
printf("%d\n",2>3); //0
printf("%d\n",22>3);//1
printf("%d\n",12>3&&8<6); //0
printf("%d\n",12>3||8<6); //1
printf("%d\n",12>3 && !(8<6)); //1
截断法则:
逻辑与运算中,前边的表达式结果为假,后边的表达式不再执行,直接返回假
逻辑或运算中,前边的表达式结果为真,后边的表达式不再执行,直接返回真
练习:
#include <stdio.h>
int main()
{
int a=5,b=6,c=7,d=8,m=2,n=2;
(m=a>b)&&(n=c>d);
printf("%d %d",m,n); //0 2
}
1.2位运算符
二进制数01
& |^ ~ << >>
& 位与:全1则1,有0则0
| 位或:有1则1,全0则0
^ 异或:相同为0,不同为1
~ 取反:1---->00------>1
实现两个变量值的交换:
int a=12,b=10;
int temp=0;
temp=a;
a=b;
b=temp;
printf("%d %d\n",a,b);
2)
a=a^b;//0110==6
b=a^b;//0110 1010 1100=12
a=a^b;//0110 1100 1010=10
printf("%d %d\n",a,b);
计算机中,整数以二进制的补码形式存储,计算的
原码、反码、补码
原码、反码、补码 解释原码、反码和补码是在计算机中用于表示有符号整数的三种不同方式。它们是用来处理负数的编码方式,常见于计算机系统中的位运算和算术运算。
1. 原码(Sign-Magnitude)
定义: 最简单直观的表示方式,其中最高位(最左边的位)表示符号位,0表示正数,1表示负数,其余位表示数值部分。
- 例子: 对于一个8位有符号整数,正数和负数的原码表示如下:
+3
的原码:00000011
-3
的原码:10000011
特点:
- 最高位为符号位,其余位表示数值部分。
- 容易理解和实现,但对于运算中的溢出和零有特殊处理。
2. 反码(One’s Complement)
定义: 正数的反码与原码相同,负数的反码是对其原码除符号位外的每一位取反。
- 例子: 使用8位有符号整数的反码表示如下:
+3
的反码:00000011
-3
的反码:11111100
特点:
- 相对于原码,计算负数的反码简单,但存在两个零(正零和负零),且存在算术运算中的特殊情况。
3. 补码(Two’s Complement)
定义: 正数的补码与原码相同,负数的补码是其反码加1。
- 例子: 使用8位有符号整数的补码表示如下:
+3
的补码:00000011
-3
的补码:11111101
特点:
- 补码是计算机中最常用的有符号整数表示方式,它只有一个零(用全0表示),没有正零和负零的区分。
- 计算机硬件可以使用补码快速执行加法和减法运算,且只需一组加法器实现。
比较和应用:
- 原码是最直观的表示方式,但不适合运算。
- 反码在一些历史系统中使用,如机器编码和传统硬件。
- 补码是目前主流的表示方式,广泛用于现代计算机体系结构中,允许有效的运算和减少硬件实现成本。
在计算机中,CPU会根据具体的指令集来进行原码、反码、补码之间的转换和运算,这些码制对于程序员来说可能不需要直接处理,但了解其基本概念有助于理解整数运算和二进制表示的细节。
原码 | 反码 | 补码 | |
---|---|---|---|
正数 | 相同 | 相同 | 相同 |
负数 | 相同 | 除符号位外,其他按位取反 | 反码+1 |
int4字节=32位 1字节=8位
符号位:最左边0正数1负数
12:
00000000000000000000000000001100
-12:
10000000000000000000000000001100
int a=12,b=-10; //12:1100 10:1010
int c=a&b;
printf(“%d\n”,c); //4
12补码:
00000000000000000000000000001100
-10原码:
10000000000000000000000000001010
-10反码:
11111111111111111111111111110101
-10补码:
11111111111111111111111111110110
12补码&-10补码:
00000000000000000000000000001100
11111111111111111111111111110110
00000000000000000000000000000100===4
~取反:1–》00–>1
int a=7;
int c=~a;
printf(“%d\n”,c);//-8
=========================
7补码:
00000000000000000000000000000111
~:补码
111111111111111111111111111110001000=80111
反码:
11111111111111111111111111110111
原码:
10000000000000000000000000001000=-8
<<左移
左移n位,右边补充n个0
6<<2==24 6 十进制数转换为2进制数
公式:
62^2=24 ^ 异或:相同为0,不同为1
-62^2=-24
>>右移
右移n位,最右边舍弃
6>>2==1
公式:
6/2^2=1
-6/2^2=-2 (小数点后大于直接进位) -1.5 -2 -1 -2
置一公式:a|(1<<n)
置零公式:a&(~(1<<n))
这两个公式看起来是关于位操作的。让我们逐个解释和如何在C语言中使用它们。
公式解释
- 置一公式:
a | (1 << n)
- 这个公式的作用是将变量
a
的第n
位设为1,其余位保持不变。 1 << n
表示将1左移n
位,即在二进制中只有第n
位为1,其余位为0。|
操作符执行按位或操作,即两个相应位中只要有一个为1,则结果为1。
- 这个公式的作用是将变量
- 置零公式:
a & (~(1 << n))
- 这个公式的作用是将变量
a
的第n
位设为0,其余位保持不变。 1 << n
仍然是将1左移n
位,产生一个只有第n
位为1的值。~(1 << n)
是对1 << n
的按位取反操作,即将其除了第n
位外的所有位取反。&
操作符执行按位与操作,即两个相应位中只有都为1时,结果为1。
- 这个公式的作用是将变量
在C语言中的使用
在C语言中,可以将这些公式直接用作赋值语句或者表达式的一部分。例如:
// 将变量 a 的第 n 位设为1
a = a | (1 << n);
// 将变量 a 的第 n 位设为0
a = a & (~(1 << n));
这里假设 a
是一个整数类型的变量,如 int
或者 unsigned int
。这些操作是针对 a
的二进制表示进行的,直接影响其在内存中的比特位。
示例
假设 a
的二进制表示为 1010
(十进制为10),我们想要将第2位(从右往左数,从0开始)设为1和0:
- 置一操作:
- 初始
a
的二进制是1010
,执行a | (1 << 2)
后,得到1010 | (1 << 2) = 1010 | 0100 = 1110
,即十进制为14。
- 初始
- 置零操作:
- 如果我们有
a
是1010
,执行a & (~(1 << 2))
后,得到1010 & (~(1 << 2)) = 1010 & 1011 = 1010
,即十进制还是10,但第2位变成了0。
- 如果我们有
这些操作在嵌入式编程、位掩码操作等领域非常常见,可以高效地设置或清除特定的位,而无需修改其他位。
:::info
以下程序升输出结果是()。
int main()
{
char x=040; //1 000 000 ==0100
printf(“%o\n”,x<<1);
return 0;
}
A.100 B.80 C.64 D.32
:::
答案解析
在这个程序中,输出结果是 100
。
让我们详细解释一下:
- 变量初始化:
char x = 040;
这里的 040
是一个八进制数,转换为十进制是 32
。因此,x
的值为 32
。
- 位左移操作:
printf(“%o\n”, x << 1);x << 1
表示将 x
的二进制表示向左移动一位。对于 32
的二进制表示为 00100000
,左移一位后变成 01000000
。
- 输出格式化:
printf(“%o\n”, x << 1);%o
是 printf
格式化输出的控制字符,表示以八进制形式输出。因此,01000000
的八进制表示是 100
。
综上所述,程序运行后的输出结果是 100
。
答案解析当我们使用位左移操作符 <<
时,它将一个数的二进制表示向左移动指定的位数。在C语言中,左移操作符的形式是 a << b
,其中 a
是要进行移位的数,b
是要移动的位数。
对于题目中的情况:
- 给定
a = 13
- 求
a << 2
的十进制数值
步骤解析:
- 确定
a
的二进制表示:a = 13
的二进制表示是1101
。
- 进行位左移操作
a << 2
:- 将
1101
向左移动两位。
- 将
- 左移操作的结果:
- 移动后的结果是
110100
。
- 移动后的结果是
- 转换为十进制数值:
110100
的二进制转换为十进制是52
。
因此,a << 2
的十进制数值为 52
。
1.3关系运算符
=<<===!=
==等于 =赋值
2–9x>2&&x<9
关系运算符内容解析
关系运算符
在C语言中,关系运算符用于比较两个值,并返回一个布尔值(1表示真,0表示假)。
- 大于 (
>
):如果左操作数大于右操作数,则条件为真。- 示例:
x > 2
表示x
大于2
。
- 示例:
- 大于等于 (
>=
):如果左操作数大于或等于右操作数,则条件为真。- 示例:
x >= 2
表示x
大于或等于2
。
- 示例:
- 小于 (
<
):如果左操作数小于右操作数,则条件为真。- 示例:
x < 9
表示x
小于9
。
- 示例:
- 小于等于 (
<=
):如果左操作数小于或等于右操作数,则条件为真。- 示例:
x <= 9
表示x
小于或等于9
。
- 示例:
- 等于 (
==
):如果两个操作数相等,则条件为真。- 示例:
x == 5
表示x
等于5
。
- 示例:
- 不等于 (
!=
):如果两个操作数不相等,则条件为真。- 示例:
x != 0
表示x
不等于0
。
- 示例:
逻辑运算符
逻辑运算符用于组合和操作布尔值。
- 逻辑与 (
&&
):如果两个操作数都为真,则条件为真。- 示例:
x > 2 && x < 9
表示x
大于2
并且小于9
。
- 示例:
- 逻辑或 (
||
):如果两个操作数中有一个为真,则条件为真。- 示例:
x < 2 || x > 9
表示x
小于2
或者大于9
。
- 示例:
- 逻辑非 (
!
):用于翻转操作数的逻辑状态。如果条件为真,则逻辑非将其变为假,反之亦然。- 示例:
!(x == 5)
表示x
不等于5
。
- 示例:
示例
如果我们有一个变量 int x = 6;
,我们可以使用上述关系运算符和逻辑运算符来进行条件判断:
if (x > 2 && x < 9) {
// 如果 x 大于 2 并且小于 9,则执行这里的代码
printf("x 在区间 (2, 9) 内\n");
} else {
// 否则执行这里的代码
printf("x 不在区间 (2, 9) 内\n");
}
这段代码将根据 x
的值判断是否在区间 (2, 9)
内,并输出相应的消息。
1.4三目运算符(选择运算符)
三目运算符 解析三目运算符,也称为条件运算符,是一种在很多编程语言中都存在的特殊运算符。它允许根据条件的真假来选择执行不同的操作或返回不同的值。
语法和用法
在大多数编程语言中,三目运算符的语法如下:
condition ? expr1 : expr2
其中:
condition
是一个布尔表达式或者可以转换为布尔值的表达式。- 如果
condition
为真,则整个表达式的值为expr1
。 - 如果
condition
为假,则整个表达式的值为expr2
。
示例
让我们看一个简单的例子来说明三目运算符的用法:
int a = 10;
int b = 20;
int max = (a > b) ? a : b;
// 上述代码等效于以下的if-else语句:
// int max;
// if (a > b) {
// max = a;
// } else {
// max = b;
// }
printf("最大值是:%d\n", max);
在这个例子中,如果 a
大于 b
,则 max
被赋值为 a
;否则 max
被赋值为 b
。在输出语句中,将打印出 max
的值,这里是 20
。
特点和注意事项
- 简洁性: 三目运算符能够在简短的表达式中实现条件选择,比起使用
if-else
结构,它更加简洁。 - 返回值: 三目运算符总是有一个返回值,因此可以嵌套使用或者用作函数的返回值。
- 可读性: 尽管它很常用,但在复杂的逻辑判断中,使用过多的三目运算符可能会降低代码的可读性。
其他语言中的三目运算符
在其他编程语言中,三目运算符的使用方式基本类似,例如在 Python 中是 expr1 if condition else expr2
,在 Java 和 JavaScript 中也是 condition ? expr1 : expr2
。
总结来说,三目运算符是一种灵活且常用的条件选择方式,可以简化代码并增强可读性,但应适度使用以保持代码清晰和易于维护。
单目运算符: ~ ++ – !
1.5赋值运算符
=+=-=*=/=%=
a-=5; //a=a-5;
1.6 运算符优先级
单算移关与异或逻条赋
单目运算符:~+±-!
算术运算符: /%±
移位运算符: <<>>
关系运算符: >>=<<===!=
位与运算符: &
异或运算符: ^
位或运算符: |
逻辑运算符: &&||
条件运算符: ?:
赋值运算符: =+=-==/=%=
解析让我们来计算表达式 (b >> 2) / (b >> 1)
的值,其中 b = 2
。
步骤分析:
- 位右移操作:
b >> 2
表示将变量b
的二进制表示向右移动两位。- 对于
b = 2
,其二进制表示是00000010
。 b >> 2
向右移动两位后,得到00000000
,即十进制0
。
- 计算
(b >> 2) / (b >> 1)
:b >> 1
表示将b
的二进制表示向右移动一位。- 对于
b = 2
,b >> 1
向右移动一位后,得到00000001
,即十进制1
。
- 进行除法运算:
- 现在我们有
(b >> 2) = 0
和(b >> 1) = 1
。 - 所以,表达式
(b >> 2) / (b >> 1)
等价于0 / 1
。
- 现在我们有
- 计算结果:
0 / 1
的值为0
。
结论:
因此,表达式 (b >> 2) / (b >> 1)
的值是 0
,所以答案是 A. 0。
解析让我们逐步分析这个表达式 c = a ^ b << 2;
并确定 c
的二进制值。
给定的变量初始化:
char a = 3;
// 二进制表示为00000011
int b = 6;
// 二进制表示为00000000 00000110
char c;
//c
尚未初始化,我们将计算它的值。
步骤分析:
- 位左移操作
b << 2
:b
是整数,b << 2
表示将b
的二进制表示向左移动两位。- 对于
b = 6
,其二进制表示是00000000 00000110
。 b << 2
向左移动两位后,得到00000000 00011000
。
- 按位异或操作
a ^ (b << 2)
:a
的二进制表示是00000011
。(b << 2)
的结果是00011000
。
然后执行按位异或操作: ```00000011 (a) ^ 00011000 (b << 2)
- 00011011
结论:
根据以上计算,表达式 c = a ^ b << 2;
的计算结果是 00011011
,即二进制形式。
因此,答案是 A. 00011011。
解析
步骤分析:
- 变量初始化:
int x = 2;
int y = 3;
int z = 4;
- 计算
y > !z
:!z
表示取z
的逻辑非,因为z
是非零的,所以!z
的值为0
。- 所以,表达式变为
y > 0
,即3 > 0
。 - 因此,
y > !z
的结果为真,也就是1
(在C语言中,真为1,假为0)。
- 计算
x + (y > !z)
:x
的值是2
。(y > !z)
的值是1
。- 所以,
x + (y > !z)
变成了2 + 1
。
结果:
因此,表达式 x + (y > !z)
的值为 3
。
答案是 3。
标点符号
英文,;[ ]{}()…
分隔符
空格tab\n
[2]变量
程序运行过程中会发生变化
格式:
存储类型 数据类型 变量名
int a;
存储类型:决定变量存储位置
数据类型:决定变量开辟空间大小
变量名:遵循标识符命名规则
名字 | 字节大小 | 取值范围 | |
---|---|---|---|
int | 整型 | 4 | -2,147,483,648 到 2,147,483,647 |
char | 字符型 | 1 | 0 到 255 或 -128 到 127 |
short | 短整型 | 2 | -32,768 到 32,767 |
long | 长整型 | 8 | -2,147,483,648 到 2,147,483,647 或 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807,具体取决于平台。 |
float | 单精度浮点型 | 4 | -3.4E+38 到 +3.4E+38 |
double | 双精度浮点型 | 8 | -1.7E+308 到 +1.7E+308 |
printf(“%ld\n”,sizeof(long));
局部变量和全局变量的区别:
局部变量 | 全局变量 | |
---|---|---|
定义位置 | 函数体内部 | 函数体外部 |
初值 | 未初始化,值是随机值 | 未初始化,值是0 |
存储位置 | 栈区 | 全局区 |
生命周期 | 同当前函数体共存亡 | 同整个程序共存亡 |
作用域 | 当前函数体内部 | 整个程序 |
局部变量和全局变量的区别局部变量(Local variables)和全局变量(Global variables)是编程中常见的概念,它们之间的主要区别如下:
- 作用域(Scope):
- 局部变量的作用域仅限于定义它们的特定代码块(通常是函数内部)。出了这个代码块,局部变量就不再有效。
- 全局变量的作用域则更广泛,它们定义在程序的任何地方(通常是在函数外部),整个程序都可以访问这些变量。
- 生存期(Lifetime):
- 局部变量的生存期仅限于其所属的代码块执行期间。一旦代码块执行完毕,局部变量就会被销毁,释放其占用的内存。
- 全局变量在程序开始运行时创建,在程序运行期间一直存在,直到程序结束或显式销毁。
- 访问权限:
- 局部变量通常只能被定义它们的代码块内部的语句访问和修改。
- 全局变量可以在程序的任何地方被访问和修改。这也使得全局变量具有潜在的风险,因为任何函数都可以改变全局状态,导致程序的行为难以预测和调试。
- 命名冲突:
- 局部变量允许在不同的函数中使用相同的名称,因为它们的作用域是相互独立的。同样的名称可以在不同函数中分别使用而不会发生冲突。
- 全局变量一般来说应当避免过多使用,因为它们的作用域过于广泛,可能会导致命名冲突和程序维护上的困难。
在实际编程中,为了避免副作用和不必要的复杂性,通常建议尽可能使用局部变量来限制变量的作用域,只有在确实需要在程序的多个地方共享状态时才使用全局变量。
[3]常量
程序运行过程中不会发生变化
程序运行过程中不会发生变化
3.1整型常量
八进制十进制十六进制
3.2字符常量
字符由’‘包裹一个字符
字符串由" "包裹,由’\0’作为字符串的结束标志
字符数组----》
3.3浮点型常量
floatdouble
3.4标识常量
宏定义:<br />格式:#define宏名 常量值或表达式或代码段<br />宏名:一般用大写表示,为了和普通变量区分开<br />注意:先原样替换,再计算
标签:反码,语言,int,基础,补码,运算符,二进制,原码
From: https://blog.csdn.net/qq_46950007/article/details/140157909