Explicación detallada de los operadores - lenguaje C

Tabla de contenido

1. Clasificación de los operadores:

2. Operadores aritméticos

3. Operador de turno 

3.1 Operador de desplazamiento a la izquierda

3.2 Operador de turno a la derecha

4. Operadores bit a bit 

5. Operador de asignación 

6. Operadores unarios

6.1 Introducción a los operadores unarios 

7. Operadores relacionales

8. Operadores lógicos 

9. Operadores Condicionales 

10. Expresiones de coma 

11. Referencias a subíndices, llamadas a funciones y miembros de estructura 

12. Evaluación de expresión 

12.1 Conversiones de tipos implícitas 

12.2 Conversiones aritméticas 

12.3 Propiedades de los operadores 


1. Clasificación de los operadores:

  算术操作符
  移位操作符
  位操作符
  赋值操作符
  单目操作符
  关系操作符
  逻辑操作符
  条件操作符
  逗号表达式
  下标引用、函数调用和结构成员

2. Operadores aritméticos

                                  +   -  *  /  %

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

3. Operador de turno 

<< El operador de desplazamiento a la izquierda desplaza la secuencia binaria a la izquierda
>> El operador de desplazamiento a la derecha desplaza la secuencia binaria a la derecha

Hablar de operadores shift es hablar de binario

Hay tres formas de representación binaria de números enteros: código original código complementario código inverso

Los códigos original y complemento de los enteros positivos son los mismos

Se calcula el complemento a uno y el complemento de enteros negativos

bit de signo 0: indica un número positivo

            1 - indica un número negativo

Los enteros se almacenan en complemento a dos en la memoria

               int a = 5
原码 000000000000000000000000000000000101
反码 000000000000000000000000000000000101
补码 000000000000000000000000000000000101
                               int a = -5
原码 10000000000000000000000000000101
反码 11111111111111111111111111111010 (原码的符号位不变,其他位取反的就是补码)
补码 11111111111111111111111111111011  (反码+1就是补码)

3.1 Operador de desplazamiento a la izquierda

Desplazamiento a la izquierda: Es descartar el lado izquierdo de la secuencia binaria y agregar 0 al lado derecho

int main()
{
	int a = 5;
	int b = a << 1;
	printf("%d\n", a);
	printf("%d\n", b);
	return 0;
}

 resultado de ejecución del programa

int main()
{
	int a = -5;
	int b = a << 1;
	printf("%d\n", a);
	printf("%d\n", b);
	return 0;
}

resultado de ejecución del programa

Nota: Los valores impresos por el compilador son todos los códigos originales 

Reglas de Conversión de Número Negativo Complemento de Código Original y Código Complemento

3.2 Operador de turno a la derecha

Cambiar a la derecha en dos

Desplazamiento aritmético a la derecha: el lado derecho se descarta y el lado izquierdo se rellena con el bit de signo original

Desplazamiento lógico a la derecha: descartar a la derecha, agregar 0 a la izquierda 

Si se trata de un desplazamiento aritmético a la derecha o un desplazamiento lógico a la derecha depende del compilador

Nota: Para los operadores de desplazamiento, no desplace los bits negativos, esto no está definido por el estándar  

4. Operadores bit a bit 

& //De acuerdo con el bit (binario) y (siempre que el bit binario correspondiente tenga 0, es 0, y solo todos los 1 son 1) | // De acuerdo
con  el bit (binario) o (siempre que el bit binario correspondiente bit binario tiene 1, es 1, solo Todos los 0 son 0)
^ //Exclusivo o por bits (binarios) (los bits binarios correspondientes son 0, y los diferentes son 1)
Nota: Sus operandos deben ser enteros

int main()
{
	int a = 3;
	int b = -5;
	int c = a & b;
	int d = a | b;
	int e = a ^ b;
	printf("%d\n", c);
	printf("%d\n", d);
	printf("%d\n", e);

	return 0;
}
00000000000000000000000000000011  -> 3的补码
11111111111111111111111111111011  -> -5的补码

(再次提醒,编译器打印出来的是原码,而正数原码反码补码相同)
00000000000000000000000000000011  -> 3&-5的结果 结果是3

(补码)
11111111111111111111111111111011  -> 3|-5的结果
10000000000000000000000000000101  (原码) 结果是-5

(补码)
11111111111111111111111111111000  -> 3^-5的结果
10000000000000000000000000001000  (原码) 结果是-8

resultado de ejecución del programa

Una pregunta de entrevista pervertida:

No se puede crear una variable temporal (la tercera variable) para realizar el intercambio de dos números

#include <stdio.h>
int main()
{
   int a = 10;
   int b = 20;
   a = a^b;
   b = a^b;
   a = a^b;
   printf("a = %d b = %d\n", a, b);
   return 0;
}

Los principiantes no esperan saberlo, solo sepan que existe tal método.

5. Operador de asignación 

El operador de asignación es un gran operador que le permite obtener un valor con el que no estaba satisfecho antes. Es decir, puedes reasignarte a ti mismo.

int weight = 120;//体重
weight = 89;//不满意就赋值
double salary = 10000.0;
salary = 20000.0;//使用赋值操作符赋值

operador de asignación compuesto 

+= -= *= /= %= >>= <<= &= |= ^=

Por ejemplo: int x += 2 ; //x = x+2

6. Operadores unarios

6.1 Introducción a los operadores unarios 

! Operación lógica inversa
- valor negativo
+ valor positivo
&
tamaño de dirección de la longitud del tipo de operando (en bytes)
~ inversión binaria bit a bit de un número
-- preposición, posposición --
++ preposición, posfijo ++
* operador indirecto (operador de desreferencia)
( tipo) emitir 

En lenguaje C, 0 significa falso, distinto de cero significa verdadero

int num =10;
if(num)
{
   printf("hehe\n);
}

//!num 就是假 if语句不进入

1. sizeof (nombre de la matriz), el nombre de la matriz no es la dirección del primer elemento de la matriz, el nombre de la matriz representa la matriz completa y el cálculo es el tamaño de la matriz completa. Excepto en este caso, todos los nombres de la matriz representan la dirección del primer elemento de la matriz. 

 sizeof es un operador, no una función, calcula el tamaño de memoria que ocupa la variable creada por el tipo, y la unidad es byte.

La expresión en sizeof() no participa en el cálculo 

Una pregunta desagradable sobre el tamaño de

#include <stdio.h>
int i;
int main()
{
    i--;
    if (i > sizeof(i))
    {
        printf(">\n");
    }
    else
    {
        printf("<\n");
    }
    return 0; 
}

P: ¿Qué producirá el programa?

Explicación: primero, si la variable global no se inicializa, se establecerá en 0 de forma predeterminada, por lo que el valor de i es 0 en este momento; y el operador sizeof, su valor de retorno es size_t, y size_t representa un número sin signo, aquí esta La expresión necesita realizar una conversión aritmética (i > sizeof(i)), y el compilador convertirá automáticamente la i izquierda en datos enteros sin signo. El entero sin signo correspondiente a -1 es un número muy grande, superior a 4 u 8, por lo que el resultado final es imprimir ">".

& toma dirección y * operador de acceso indirecto (operador de desreferencia)

int main()
{
	//& 取地址操作符
	//* 解引用操作符(间接访问操作符)

	int a = 10;
	int* pa = &a;
	*pa = 20;//* - 解引用操作符
	//
	//*&a ==> a;
	return 0;
}

7. Operadores relacionales

> >= < <= != ==

nada que decir 

8. Operadores lógicos 

&& lógico y
|| lógico o

AND lógico La expresión completa es verdadera solo si las expresiones izquierda y derecha son verdaderas

Lógico o solo si las expresiones izquierda y derecha son falsas, la expresión completa es falsa 

int main()
{
	int i = 0, a = 0, b = 2, c = 3, d = 4;
	//i = a++ && ++b && d++;

	i = a++ || ++b || d++;

	printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
	return 0;
}

Análisis: i = a++ || ++b || d++; a++ usa a primero, luego ++, ay comienza en 0, baja, ++b, primero b++, en uso, y el valor de toda la expresión Si ya es cierto, el siguiente d++ no se ejecutará, por lo que el resultado de ejecución del programa es 1, 3, 3, 4.

9. Operadores Condicionales 

exp1? exp2 : exp3

Si la afirmación 1 es verdadera, el resultado de la expresión es la afirmación 2, de lo contrario, es la afirmación 3 

int main()
{
	int a = 3;
	int b = 5;
	int m = (a > b ? a : b);
	printf("%d\n", m);
	return 0;
}

10. Expresiones de coma 

Las expresiones de coma son expresiones múltiples separadas por comas.
Las expresiones de coma se ejecutan secuencialmente de izquierda a derecha. El resultado de toda la expresión es el resultado de la última expresión. 

int main()
{
	int a = 1;
	int b = 2;
	int c = (a > b, a = b + 10, a, b = a + 1);
	printf("a=%d b=%d\n", a, b);
	printf("%d\n", c);
	return 0;
}

11. Referencias a subíndices, llamadas a funciones y miembros de estructura 

1. [ ] operador de referencia de subíndice

Operando: un nombre de matriz + un valor de índice

int arr[10];//Crear una matriz
arr[9] = 10;//Operador de referencia de subíndice práctico.
Los dos operandos de [ ] son ​​arr y 9

2. ( ) El operador de llamada de función
acepta uno o más operandos: el primer operando es el nombre de la función y los operandos restantes son los parámetros pasados ​​a la función.

Nota: no puede haber parámetros

3. Acceder a un miembro de una estructura
 Estructura Nombre del miembro
-> Puntero de estructura -> Nombre del miembro 

#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;
}

12. Evaluación de expresión 

El orden en que se evalúan las expresiones está determinado en parte por la precedencia y la asociatividad de los operadores.
Asimismo, es posible que sea necesario convertir los operandos de algunas expresiones a otros tipos durante la evaluación. 

12.1 Conversiones de tipos implícitas 

Las operaciones aritméticas de enteros de C siempre se realizan con al menos la precisión del tipo integral predeterminado. Para lograr esta precisión, los operandos de caracteres y enteros cortos en las expresiones se convierten en tipos de enteros simples antes de su uso, una conversión conocida como promoción de enteros.


La importancia de la promoción de enteros :
la operación de enteros de la expresión debe ejecutarse en el dispositivo informático correspondiente de la CPU.La longitud en bytes del operando de la unidad aritmética entera (ALU) en la CPU es generalmente la longitud en bytes de int, y es también la longitud en bytes de la CPU La longitud de los registros de propósito general. Por lo tanto, incluso si la CPU realmente realiza la adición de dos tipos de caracteres, primero debe convertirse a la longitud estándar del operando entero en la CPU. Es difícil para una CPU de propósito general (CPU de propósito general) agregar directamente dos bytes de 8 bits directamente (aunque puede haber tales instrucciones de adición de bytes en las instrucciones de la máquina). Por lo tanto, los diversos valores enteros en la expresión cuya longitud puede ser menor que la longitud de int deben convertirse a int o int sin signo antes de enviarse a la CPU para su cálculo. 

carácter a,b,c;
...
a = b + c;

Los valores de b y c se convierten en enteros normales antes de realizar la operación de suma.

Una vez completada la operación de suma, el resultado se trunca antes de almacenarse en a.

¿Cómo llevar a cabo la mejora global?

La promoción de enteros se promueve de acuerdo con el bit de signo del tipo de datos de la variable

//负数的整形提升
char c1 = -1;
变量c1的二进制位(补码)中只有8个比特位:
1111111
因为 char 为有符号的 char
所以整形提升的时候,高位补充符号位,即为1
提升之后的结果是:
11111111111111111111111111111111
//正数的整形提升
char c2 = 1;
变量c2的二进制位(补码)中只有8个比特位:
00000001
因为 char 为有符号的 char
所以整形提升的时候,高位补充符号位,即为0
提升之后的结果是:
00000000000000000000000000000001
//无符号整形提升,高位补0

dar dos ejemplos 

int main()
{
	char c1 = 3;
	//首先要进行整型提升
	//00000000000000000000000000000011
	//00000011 - c1
	char c2 = 127;
	//首先要进行整型提升
	//00000000000000000000000001111111
	//01111111 - c2
	

	char c3 = c1 + c2;
	//00000000000000000000000000000011
	//00000000000000000000000001111111
	//00000000000000000000000010000010
	// 这里要发生截断
	//10000010 - c3
	// 此时c1是字符型,但我们是要以整型形式打印,所以还要进行整型提升。
	//11111111111111111111111110000010 补码
	//11111111111111111111111110000001 反码 
	//10000000000000000000000001111110 原码
	//-126
	
	printf("%d\n", c3);//
	
	return 0;
}
int main()
{
   char a = 0xb6;
   short b = 0xb600;
   int c = 0xb6000000;
   if(a==0xb6)
     printf("a");
   if(b==0xb600)
     printf("b");
   if(c==0xb6000000)
     printf("c");
   return 0;
}

En el ejemplo, a y b deben plastificarse y actualizarse, pero no es necesario plastificarse ni actualizarse C. Después de plastificarse y promocionarse a y b, se convierten en números negativos, por lo que el resultado de la expresión a==0xb6, b==0xb600 es falso, pero c no sucede Si se mejora el entero, el resultado de la expresión c==0xb6000000 es verdadero
El resultado que arroja el programa es: c

int main()
{
	char c = 1;
	printf("%u\n", sizeof(c));
	printf("%u\n", sizeof(+c));
	printf("%u\n", sizeof(-c));
	return 0;
}

Siempre que c participe en la operación de expresión, se producirá la promoción plástica y se promoverá la expresión +c, por lo que sizeof(+c) es de 4 bytes. La expresión
-c también se someterá a la promoción plástica, por lo que sizeof(-c ) es de 4 bytes, pero sizeof(c) es de 1 byte. 

12.2 Conversiones aritméticas 

Si los operandos de un operador son de diferentes tipos, la operación no puede continuar a menos que uno de los operandos se convierta al tipo del otro. La siguiente jerarquía se llama conversión aritmética ordinaria

long double
double
float
unsigned long int
long int
unsigned int
int

Si el tipo de un operando es más bajo en la lista anterior, primero debe convertirse al tipo del otro operando antes de realizar la operación.

12.3 Propiedades de los operadores 

Hay tres factores que afectan la evaluación de expresiones complejas.
1. Prioridad de operadores (deben ser operadores adyacentes)
2. Asociatividad de operadores
3. Si controlar el orden de evaluación.
¿Cuál de los dos operadores adyacentes se ejecuta primero? Depende de sus prioridades. Si ambos tienen la misma prioridad, depende de su asociatividad.

Si la expresión que escribimos no puede determinar la ruta de cálculo única a través de los atributos del operador, entonces hay un problema con esta expresión
.

Por ejemplo, el código produce diferentes resultados en varios entornos de compilación.

#include <stdio.h>
int main()
{
int i = 1;
int ret = (++i) + (++i) + (++i);
printf("%d\n", ret);
printf("%d\n", i);
return 0;
}

Supongo que te gusta

Origin blog.csdn.net/m0_63562631/article/details/125821487
Recomendado
Clasificación