Explicación detallada de operadores (muy detallada)

Acceso al subíndice [ ], llamada a función ()

[] operador de referencia de subíndice

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

int arr[10];//创建数组
arr[9] = 10;//实⽤下标引⽤操作符。
[ ]的两个操作数是arr和9
3+5     35是加号的两个操作数

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.

#include <stdio.h>
void test1()
{
    
    
printf("hehe\n");
}
void test2(const char *str)
{
    
    
printf("%s\n", str);
}
int main()
{
    
    
test1(); //这⾥的()就是作为函数调⽤操作符。
test2("hello bit.");//这⾥的()就是函数调⽤操作符。
return 0;
}

Nota: El operando mínimo de una función es solo uno, es decir, solo un nombre de función. No se pasan parámetros (void).
Aquí, me gustaría mencionar que sizeof no es una función, sino un operador.

#include<stdio.h>
int main()
{
    
    
int a=10;
int n=sizeof(a)int n=sizeof a其实都一样
printf("%d\n",n);
return 0;
}

Podemos ver que la diferencia entre int n=sizeof(a) e int n=sizeof a es uno (), y la función requiere (), por lo que sizeof no es una función sino un operador.

Propiedades del operador: precedencia, asociatividad.

Los operadores en lenguaje C tienen dos atributos importantes, prioridad y asociatividad. Estos dos atributos determinan el orden de cálculo de la evaluación de la expresión (se puede aproximar como una operación matemática pero aún existen ciertas diferencias)

prioridad

Si una expresión contiene varios operadores durante la operación, ¿qué operador se debe ejecutar primero?
Para solucionar este problema se especifica la prioridad de cada operador.

 3 + 4 * 5;

En el ejemplo anterior, la expresión 3 + 4 * 5 contiene tanto el operador de suma ( + ) como el operador de multiplicación (*). Dado que la multiplicación tiene mayor prioridad que la suma, primero se calculará 4 * 5 en lugar de 3 + 4 primero. (Estas son en realidad las reglas de operación matemática)

Combinación

Cuando las prioridades de dos operadores son las mismas, es decir, cuando los operadores son los mismos, no podemos juzgar qué cálculo comenzar en función de la prioridad, por lo que en este caso es necesario utilizar la asociatividad, pero la asociatividad depende de la situación. , algunos combinarán hacia la izquierda (calculado de izquierda a derecha), otros combinarán hacia la derecha (calculado de derecha a izquierda), pero la mayoría se calculará de izquierda a derecha.

5 * 6 / 2;

En el ejemplo anterior, * y / tienen la misma prioridad. Ambos son operadores asociativos izquierdos, por lo que se ejecutan de izquierda a derecha. Primero se calcula 5 * 6 y luego 6/2. Hay muchos órdenes de prioridad de operadores. El siguiente es el orden de prioridad de algunos operadores (ordenados de mayor a menor prioridad). Se recomienda que recuerde las prioridades de estos operadores. • Paréntesis ( () ) • Operación de incremento
automático
operador (++), operador de decremento (-)
• Operadores unarios (+ y -)
• Multiplicación (*), división (/)
• Suma (+), resta (-)
• Operadores relacionales (<, > etc.)
• Operador de asignación (=)

Dado que los paréntesis tienen la prioridad más alta, puede usarlos para cambiar la precedencia de otros operadores.
inserte la descripción de la imagen aquí
Enlace de referencia de precedencia de operadores

Evaluación de expresiones

Promoción de números enteros

Las operaciones aritméticas de enteros en lenguaje C siempre se realizan con al menos la precisión del tipo entero predeterminado ( es decir, cuando el tipo de datos almacenado es menor que los 32 bits almacenados en el entero, el tipo de datos menor que 32 bits se promueve como entero ).
Para obtener Con esta precisión, los operandos cortos y de caracteres en las expresiones se convierten a enteros ordinarios antes de su uso, lo que se denomina promoción de enteros.

El significado de la promoción de números enteros.

La operación entera de la expresión debe realizarse 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 también es la longitud de el registro de propósito general de la CPU .
Por lo tanto, incluso si la CPU realiza la suma de dos tipos de caracteres, primero debe convertirse a la longitud estándar del operando entero en la CPU . ( De todos modos, son la longitud estándar de los operandos enteros que se van a convertir, de modo que la longitud de bytes aumentada se puede usar para hacer que la precisión sea más precisa )
Es difícil para una CPU de uso general implementar directamente la suma directa operación de dos bytes de 8 bits (aunque la máquina puede tener una instrucción de adición de bytes en la instrucción
). Por lo tanto, todos los 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 poder enviarse a la CPU para realizar operaciones.

//实例1
char a,b,c;
char a=5;
//00000000 00000000 00000000 00000101
//00000101(截断后存储到a中)
char b=127;
//00000000 00000000 00000000 01111111
01111111(截断后存储到b中)
char a = b + c;
//00000000 00000000 00000000 00000101  a
//00000000 00000000 00000000 01111111  b
//00000000 00000000 00000000 10000100
//10000100(截断后存储到c中)
printf(“%d”,c)
//这里还是要整型提升
//11111111 11111111 11111111 10000100 补码
//10000000 00000000 00000000 01111011 反码
//10000000 00000000 00000000 01111010 原码
//%d是按照10进制的形式打印有符合的整数
/*可能会有人对这有疑惑11111111 11111111 11111111 10000100 补码
为什么左边全是1,其实是因为在整形提升时最高位补符号位*/
b和c的值被提升为普通整型,然后再执⾏加法运算。
加法运算完成之后,结果将被截断,然后再存储于a中

Cómo mejorar en general

  1. La promoción de enteros con signo se promueve según el bit de signo del tipo de datos de la variable.
  2. Se promocionan los enteros sin signo y los bits altos se rellenan con 0
//负数的整形提升
char c1 = -1;
变量c1的⼆进制位(补码)中只有8个⽐特位:
1111111
因为 char 为有符号的 char
所以整形提升的时候,⾼位补充符号位,即为1
提升之后的结果是:
11111111111111111111111111111111

//正数的整形提升
char c2 = 1;
变量c2的⼆进制位(补码)中只有8个⽐特位:
00000001
因为 char 为有符号的 char
所以整形提升的时候,⾼位补充符号位,即为0
提升之后的结果是:
00000000000000000000000000000001
//⽆符号整形提升,⾼位补0

Conversión aritmética

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 operando . La siguiente jerarquía se llama transformaciones aritméticas ordinarias.

1.long double
2.double
3.float
4.unsigned long int
5.long int
6.unsigned int
7.int
//如果某个操作数的类型在上⾯这个列表中排名靠后,那么⾸先要转换为另外⼀个操作数的类型后执⾏
运算。
//比如int和double,因为int排在double后面,所以要将int转换为double类型再执行运算

Análisis de expresión de problemas.

Las siguientes expresiones entran en conflicto con los métodos de cálculo matemático, así que preste especial atención a ellas.

Expresión 1

//表达式的求值部分由操作符的优先级决定。
//表达式1
a*b + c*d + e*f

Mucha gente calculará a b, c d, e f al mismo tiempo porque la prioridad de es mayor que +,
pero la prioridad no determina que el tercer * se ejecutará antes que el primero +, porque solo se puede determinar operadores aritméticos,
por lo que el orden informático de la expresión podría ser:

1:a*b
2:c*d
3:a*b + c*d
4:e*f
5:a*b + c*d + e*f

Pero también es posible

a*b
c*d
e*f
a*b + c*d
a*b + c*d + e*f

Expresión 2

//表达式2
c + --c;

Igual que arriba, la prioridad del operador solo puede determinar si la operación de decremento – precede a la operación de +, pero no tenemos forma de saber si el operando izquierdo del operador + se obtiene antes o después del operando derecho, Entonces los resultados son impredecibles y ambiguos
, por ejemplo:

intc=1;
c+--c

Si la primera c es 1, entonces c+ --c=1+0=1,
y si la primera c se asigna después de –c, entonces c+ --c=0+0=0,

así que no escribas el código como esto, de lo contrario terminará, ni siquiera sé cómo surgió.

Expresión 3

//表达式3
int main()
{
    
    
int i = 10;
i = i-- - --i * ( i = -3 ) * i++ + ++i;
printf("i = %d\n", i);
return 0;
}

Resultados de la prueba de expresión 3 en diferentes compiladores: resultados del programa de expresión ilegal
inserte la descripción de la imagen aquí

Expresión 4

#include <sdtio.h>
int fun()
{
    
    
static int count = 1;
return ++count;
}
int main()
{
    
    
int answer;
answer = fun() - fun() * fun();
printf( "%d\n", answer);
return 0;
}

En el código anterior respuesta = fun() - fun() * fun(); solo podemos saberlo a través de la prioridad del operador: la
multiplicación se calcula primero, luego la resta, pero el orden de llamada de las funciones no puede ser determinado por la prioridad del operador. Claro

Expresión 5

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

Cuando se ejecuta el primer + en este código, no se sabe si se ejecutará el tercero + +, porque la prioridad y asociatividad del operador no pueden determinar si se ejecutan el primer + y el tercer + anterior.

Resumir

Incluso con la prioridad y asociatividad de los operadores, es posible que la expresión que escribimos aún no pueda determinar la ruta de cálculo única a través de los atributos del operador. Entonces esta expresión es potencialmente riesgosa. Se recomienda no escribir expresiones sofisticadas. estilo, de lo contrario Estarás confundido

Supongo que te gusta

Origin blog.csdn.net/2301_79178723/article/details/132363185
Recomendado
Clasificación