Lenguaje C elemental - Explicación detallada de los operadores (Parte 1)

"Si no vuelas, volarás hacia el cielo; si no cantas, te convertirás en un éxito de taquilla". Hoy, aprendamos sobre los operadores.

1. Clasificación de los operadores

Operadores aritméticos + - * / %
Operadores de desplazamiento Operadores bit a bit Operadores << >>
de asignación Operadores unarios Operadores relacionales Operadores lógicos Operadores condicionales Expresiones de coma Referencias de subíndices, llamadas a funciones y miembros de estructura& | ^
= += -= *= /=...
! sizeof ++ -- ...
> >= < <= == !=
&& ||
? :
,
[] () ->

2. Operadores aritméticos

+ - * / %

Nota : 1. Además %del operador, varios otros operadores pueden actuar sobre números enteros y de punto flotante.
2. Para /los operadores, si ambos operandos son enteros, se realiza la división de enteros. Y siempre que haya números de punto flotante, se realiza la división de números de punto flotante.
3. Los dos operandos% del operador deben ser enteros y se devuelve el resto después de la división de enteros.

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
    
    
	int m = 7 / 2;
	printf("%d\n", m);
	double n = 7.0 / 2;
	printf("%lf\n", n);
	int o = 7 % 2;
	printf("%d\n", o);
	return 0;
}

inserte la descripción de la imagen aquí

3. Operador de turno

>>右移操作符 <<左移操作符

Nota: Los operandos de los operadores de desplazamiento solo pueden ser números enteros.

Para un número entero, 4 bytes = 32 bits. Cuando un entero se escribe como una secuencia binaria, tiene 32 bits. Para enteros con signo, el bit más alto es el bit de signo, 符号位是1表示负数,符号位是0表示正数。para enteros sin signo, no hay bit de signo y todos los bits son bits válidos.

Hay tres representaciones binarias de números enteros : código original, código inverso y código complementario.
Código original: Según el signo del valor, la secuencia binaria escrita directamente es el código original.

Por ejemplo: 10este número 原码es 00000000000000000000000000001010, entonces -10el código original es 10000000000000000000000000001010.
Nota: Para números enteros positivos, el código original, el código inverso y el código complementario son los mismos, por lo que no se requiere ningún cálculo.
Para números enteros negativos, es necesario calcular el código original, el código inverso y el código complementario.

Código inverso: el bit de signo del código original permanece sin cambios, y los otros bits se invierten poco a poco. (Inversión bit a bit, el 0 original se cambia a 1 y el 1 original se cambia a 0)
Código complementario: El binario + 1 del código inverso es el código complementario.

Por lo tanto, 10este número 原码、反码、补码es todo 00000000000000000000000000001010. -10El código original es 10000000000000000000000000001010, el código inverso es 11111111111111111111111111110101, y el código complementario es 11111111111111111111111111110110. Los números enteros se almacenan en la memoria como secuencias binarias en complemento a dos. Cuando se calculan números enteros, se usa el complemento a dos.

3.1 Operador de desplazamiento a la izquierda

Regla de cambio: descartar a la izquierda, agregar 0 a la derecha

#include <stdio.h>
int main()
{
    
    
	//m:00000000000000000000000000000111
	int m = 7;
	int n = m << 1;
	//左移位原则:左边抛弃,右边补0
	//n:00000000000000000000000000001110
	//n = 2+4+8=14
	printf("%d\n", m);
	printf("%d\n", n);
	return 0;
}

inserte la descripción de la imagen aquí
Podemos encontrar que el operador de desplazamiento a la izquierda puede desempeñar un doble papel. Lo mismo es cierto para los números negativos:
inserte la descripción de la imagen aquí

3.2 Operador de turno a la derecha

Reglas de desplazamiento (hay dos tipos de operaciones de desplazamiento a la derecha):
1. Desplazamiento lógico: el izquierdo se rellena con 0 y el derecho se descarta.
2. Desplazamiento aritmético: el lado izquierdo se rellena con el bit de signo del valor original y el lado derecho se descarta.

//右移位操作符
#include <stdio.h>
int main()
{
    
    
	//a的原码:10000000000000000000000000001010
	//a的反码:11111111111111111111111111110101
	//a的补码:11111111111111111111111111110110
	//大多数编译器采用的是算术右移
	//b是算术右移(右边直接丢弃,左边补原符号位,原来是负数,左边补1,原来是正数,左边补0)
	//b的补码:11111111111111111111111111111011
	//b的反码:11111111111111111111111111111010
	//b的原码:10000000000000000000000000000101
	//b=-(1+4)=-5
	int a = -10;
	int b = a >> 1;
	printf("a=%d\n", a);
	printf("b=%d\n", b);
	return 0;
}

inserte la descripción de la imagen aquí
Podemos ver que el desplazamiento aritmético a la derecha también juega /2un papel.
Nota: Para los operadores de cambio, no cambie los bits negativos, esto no está definido por el estándar.

4. Operadores bit a bit

Los operadores bit a bit son:|(按位或)&(按位与)^(按位异或)

Nota: Sus operandos deben ser números enteros.

4.1 Bit a bit AND &

Para dos números a和b, use el operador AND bit a bit c = a&b;, primero debe escribir a和bla forma de complemento de los bits binarios y luego compararlos uno por uno.只有当两个数a和b的对应的补码都为1的时候,按位与的结果才是1,否则为0。

#include <stdio.h>
int main()
{
    
    
	int a = 3;
	int b = -5;
	int c = a & b;//按(二进制)位与
	//-5的原码:10000000000000000000000000000101
	//-5的反码:10000000000000000000000000000100
	//-5的补码:11111111111111111111111111111011
	// 3的补码: 00000000000000000000000000000011
	// 按位与:两个都为1才为1
	//       c: 00000000000000000000000000000011
	//结果为3
	printf("%d\n", c);
	return 0;
}

inserte la descripción de la imagen aquí

4.2 Bit a bit O |

Para dos números a和b, use el operador OR bit a bit c = a|b;, primero debe escribir a和bla forma de complemento de los bits binarios y luego compararlos uno por uno.只要当两个数a和b的对应的补码有一个为1的时候,按位或的结果就是1,否则为0。

#include <stdio.h>
int main()
{
    
    
	int a = 3;
	int b = -5;
	int c = a | b;//按(二进制)位或
	//-5的原码:10000000000000000000000000000101
	//-5的反码:10000000000000000000000000000100
	//-5的补码:11111111111111111111111111111011
	// 3的补码: 00000000000000000000000000000011
	// 按位或:有一个为1即为1
	// c的补码: 11111111111111111111111111111011
	// c的反码: 11111111111111111111111111111010
	// c的原码: 10000000000000000000000000000101
	//结果为-5
	printf("%d\n", c);
	return 0;
}

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

4.3 Bit a bit XOR^

Para dos números a和b, use el operador OR bit a bit c = a^b;, primero debe escribir a和bla forma de complemento de los bits binarios y luego compararlos uno por uno.两个数a和b的对应的补码相同为0,不同为1.

#include <stdio.h>
int main()
{
    
    
	int a = 3;
	int b = -5;
	int c = a ^ b;//按(二进制)位异或
	//-5的原码:10000000000000000000000000000101
	//-5的反码:10000000000000000000000000000100
	//-5的补码:11111111111111111111111111111011
	// 3的补码: 00000000000000000000000000000011
	// 按位异或:相同为0不同为1
	// c的补码: 11111111111111111111111111111000
	// c的反码: 11111111111111111111111111110111
	// c的原码: 10000000000000000000000000001000
	//结果为-8
	printf("%d\n", c);
	return 0;
}

inserte la descripción de la imagen aquí
Nota: En particular, a^a=0; a^0=a;.

A continuación, hacemos una pregunta especial: sin crear una variable temporal (sin una tercera variable), realice el intercambio de dos números.

A través del estudio anterior, sabemos cómo utilizar la tercera variable:

//实现两个数的交换
#include <stdio.h>
int main()
{
    
    
	int a = 3;
	int b = 5;
	int c = 0;
	printf("交换前a=%d,b=%d\n", a, b);
	c = a;
	a = b;
	b = c;
	printf("交换后a=%d,b=%d\n",a,b);
	return 0;
}

inserte la descripción de la imagen aquí
Entonces, ¿cómo podemos lograr la misma funcionalidad sin usar una tercera variable?

//实现两个数的交换
#include <stdio.h>
int main()
{
    
    
	int a = 3;
	int b = 5;
	printf("交换前a=%d,b=%d\n", a, b);
	a = a + b;
	b = a - b;
	a = a - b;
	printf("交换后a=%d,b=%d\n", a, b);
	return 0;
}

inserte la descripción de la imagen aquí
Aquí, solo usamos dos variables, pero todavía hay defectos, es decir, a和bcuando el valor de es muy grande, habrá un problema de desbordamiento. Aquí, necesitamos usar 异或^este operador.

//实现两个数的交换
#include <stdio.h>
int main()
{
    
    
	int a = 3;
	int b = 5;
	printf("交换前a=%d,b=%d\n", a, b);
	a = a ^ b;//a=3^5;
	b = a ^ b;//b=3^5^5=3
	a = a ^ b;//a=3^5^3=3^3^5=5
	//异或支持交换律
	printf("交换后a=%d,b=%d\n", a, b);
	return 0;
}

inserte la descripción de la imagen aquí
Nota: 异或^No hay problema de desbordamiento, pero la legibilidad no es alta y solo se limita a operaciones con números enteros.

5. Operador de asignación

Los operadores de asignación se utilizan para modificar el valor de una variable después de que se haya creado.

#include <stdio.h>
int main()
{
    
    
	int a = 3;//不是赋值,是初始化
	a = 10;//赋值
	return 0;
}

Los operadores de asignación se pueden utilizar consecutivamente, por ejemplo:

#include <stdio.h>
int main()
{
    
    
	int a = 10;
	int b = 20;
	int c = a = a + b;//连续赋值
	//连续赋值从右往左算
	//a = a + b = 30
	//c = a = 30
	printf("%d\n", c);
	return 0;
}

inserte la descripción de la imagen aquí
Sin embargo, la declaración de asignación continua no es propicia para la depuración, lo anterior int c = a = a + b;se puede dividir en:

a = a + b;
c = a;
//这样的写法更清晰爽朗且易于调试。

Operador de asignación compuesto:+= -= *= /= %= >>= <<= &= |= ^=

Todos estos operadores se pueden escribir como efectos compuestos, por ejemplo:

int a = 2;
//以下两种写法表达含义一致
a = a + 10;
a += 10;

6. Operador unario

6.1 Introducción a los operadores unarios

operador unario nombre
operador lógico inverso
- valor negativo
+ valor positivo
& tomar dirección
tamaño de la longitud de tipo del operando en bytes
~ Inverso bit a bit de un número
- - Delantero trasero - -
++ Delantero, trasero++
* operador de acceso indirecto (operador de desreferencia)
(tipo) elenco

1. El operador inverso lógico (!)

//0表示假,1表示真
#include <stdio.h>
int main()
{
    
    
	int a = 1;
	int b = 0;
	b = !a;
	printf("%d\n", b);
	return 0;
}

inserte la descripción de la imagen aquí
2. Operador de desreferencia (*)

//解引用操作符*
#include <stdio.h>
int main()
{
    
    
	int a = 10;
	int* p = &a;
	*p;//对p解引用操作,*p是通过p中存放的地址,找到p指向的对象
	//*p就是a
	return 0;
}

3. tamaño de y matrices

//sizeof计算的是类型创建变量或变量的大小,单位是字节
//sizeof计算的结果是size_t类型的
//size_t是无符号的
//对size_t类型的数据进行打印,可以用%zd
//sizeof后面的括号在括号中写的不是类型的时候,括号可以省略,这样也说明了sizeof不是函数
//sizeof是操作符-单目操作符
#include <stdio.h>
int main()
{
    
    
	int a = 10;
	printf("%zd\n", sizeof(a));
	printf("%zd\n", sizeof a);
	printf("%zd\n", sizeof(int));
	int arr[10] = {
    
     0 };
	printf("%zd\n", sizeof arr);
	printf("%zd\n", sizeof(arr[1]));
	return 0;
}

inserte la descripción de la imagen aquí
4.~ (inversión binaria de un número)

#include <stdio.h>
int main()
{
    
    
	int a = 0;
	printf("%d\n", ~a);
	//a的补码: 00000000000000000000000000000000
	// 按位取反,就是不论是不是符号位都取反
	//~a的补码:11111111111111111111111111111111
	//~a的反码:11111111111111111111111111111110
	//~a的原码:10000000000000000000000000000001
	// 符号位0为正 1为负
	//~a的值为-1
	return 0;
}

inserte la descripción de la imagen aquí
Entonces, a continuación, ¿puedes ver ~cómo usarlo?

#include <stdio.h>
int main()
{
    
    
	int a = 10;
	//000000000000000000000000000001010
	//如果我们想让从右往左数第三个数变成1该怎么做?
	// 即变成00000000000000000000000000001110为14
	//将000000000000000000000000000000001左移二
	//1<<2  00000000000000000000000000000100
	//将左移后的二进制位与a的二进制位按位或即可
	a |= (1 << 2);
	printf("%d\n", a);
	//那么,反过来,如果希望从右往左数第三个数再变为0该怎么办?
	// 只需要将下面第一个和第二个按位与就能得到第三个
	//0000000000000000000000000000001110
	//1111111111111111111111111111111011,这个可以将(1<<2)取反得到
	//0000000000000000000000000000001010
	a &= ~(1 << 2);
	printf("%d\n", a);
	return 0;
}

inserte la descripción de la imagen aquí
5. ++ --Operadores

#include <stdio.h>
int main()
{
    
    
	int a = 2;
	//++a;
	//++是一种自增1的操作
	a++;
	//前置++和后置++对于a本身没有影响,都是进行+1的操作
	printf("%d\n", a);
	return 0;
}

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
¡Pre ++ y post ++ no tienen efecto en sí mismo pero tienen efecto en los demás! Los ejemplos son los siguientes:

#include <stdio.h>
int main()
{
    
    
	int a = 2;
	int b = a++;
	//后置++:先使用,后+1
	printf("%d\n", a);
	printf("%d\n", b);
	return 0;
}

inserte la descripción de la imagen aquí

#include <stdio.h>
int main()
{
    
    
	int a = 2;
	int b = ++a;
	//前置++:先+1,后使用
	printf("%d\n", a);
	printf("%d\n", b);
	return 0;
}

inserte la descripción de la imagen aquí

前置--和后置--和前、后置++同理,大家可以自己试一下!

Muy bien, detengámonos aquí por el conocimiento sobre los operadores, y continuará actualizándose en el futuro. ¡Bienvenidos a todos a seguir prestando atención, dar me gusta y comentar!

Supongo que te gusta

Origin blog.csdn.net/qq_73121173/article/details/132131364
Recomendado
Clasificación