9. Operadores condicionales
Compuesto por signos de interrogación y dos puntos, hay tres expresiones y tres operadores, por lo que el operador condicional es el único operador ternario, exp1 es verdadero, exp2 se calcula, exp3 no se cuenta, el resultado de toda la expresión es el resultado de exp2. exp1 es falso, exp2 no se calcula, exp3 se calcula y el resultado de toda la expresión es el resultado de exp3.
exp1 ? exp2 : exp3
El efecto de los dos códigos es el mismo, que es el uso del operador condicional.
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a = 10;
int b = 20;
int m = 0;
m = (a > b ? a : b);
printf("%d\n", m);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a = 10;
int b = 20;
int m = 0;
if (a > b)
m = a;
else
m = b;
printf("%d\n", m);
return 0;
}
10. Expresiones de coma
exp1, exp2, exp3, …expN
Las expresiones de coma son múltiples expresiones 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("c=%d\n", c);
return 0;
}
11. Referencias de 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 práctico de referencia de subíndice.
Los dos operandos de [] son arr y 9.
2. () 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.
#define _CRT_SECURE_NO_WARNINGS 1
#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;
}
3. Acceder a miembros de una estructura
. 结构体.成员名
-> 结构体指针->成员名
Este es el uso del operador de acceso a miembros de la estructura.
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
struct Book
{
char name[20];
int price;
};
//结构体变量.成员
//结构体指针->成员
void Print(struct Book* pb)
{
printf("%s %d\n", (*pb).name, (*pb).price);
printf("%s %d\n", pb->name, pb->price);
}
int main()
{
struct Book b = {"C语言指南", 55};
printf("%s %d\n", b.name, b.price);
Print(&b);
return 0;
}
12. Evaluación de expresiones
El orden en el que se evalúan las expresiones está determinado en parte por la precedencia y asociatividad de los operadores.
Del mismo modo, 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 a tipos enteros simples antes de su uso, una conversión conocida como promoción de enteros .
Importancia de la promoción de números enteros :
La operación entera de la expresión debe ejecutarse en el dispositivo de operación 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 realmente realiza la suma 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 (aunque puede haber
instrucciones de suma 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.
Los valores de ayb se convierten en números enteros normales antes de realizar la operación de suma.
Una vez completada la suma, el resultado se trunca antes de almacenarse en c.
¿Cómo llevar a cabo la mejora global?
La promoción de enteros se promueve según el bit de signo del tipo de datos de la variable.
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//int - signed int
//unsigned int
//char 到底是signed char还是unsigned char是不确定的,C语言标准没有明确指定,是取决于编译器的
//在当前使用的VS上,char == signed char
int main()
{
char a = 5;
//00000000000000000000000000000101
//00000101-存进去的是这8个bit位
char b = 126;
//00000000000000000000000001111110
//01111110
char c = a + b;
//00000000000000000000000000000101-a
//00000000000000000000000001111110-b
//00000000000000000000000010000011
//10000011-c里面只能放这8个bit位
//按照符号位整形提升
//11111111111111111111111110000011
//10000000000000000000000001111100
//10000000000000000000000001111101
//-125
printf("%d\n", c);
return 0;
}
Ejemplos de mejoras de forma:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
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 1, a y b deben actualizarse con plástico, pero c no necesita actualizarse con plástico.
Después de que a y b se actualizan con plástico, se convierten en números negativos, por lo que el resultado de las expresiones a==0xb6 y b==0xb600 es falso, pero c no. Si se produce promoción plástica, el resultado de la expresión c==0xb6000000 es verdadero.
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 denomina conversiones aritméticas ordinarias .
long double
double
float
unsigned long int
long int
unsigned int
int
Si el tipo de un operando ocupa un lugar inferior en la lista anterior, la operación primero debe convertirse al tipo del otro operando.
Advertencia:
Sin embargo, las conversiones aritméticas deben ser razonables o existen algunos problemas potenciales.
float f = 3.14;
int num = f;//隐式转换,会有精度丢失
12.3 Propiedades de los operadores
Hay tres factores que afectan la evaluación de expresiones complejas.
1. La prioridad del operador
2. La asociatividad del operador
3. Si se debe controlar el orden de evaluación.
¿Cuál de dos operadores adyacentes se ejecuta primero? Depende de sus prioridades. Si ambos tienen la misma prioridad, depende de su asociatividad.
precedencia del operador
operador _ |
describir | ejemplo de uso | tipo de resultado | Combinación | si se debe controlar el orden de evaluación |
() | grupo | (expresión) | igual que la expresión |
N / A | No |
() | Llamada de función | rexp(rexp,...,rexp) | reexp | LR | No |
[ ] | referencia de subíndice | rexp[rexp] | lexp | LR | No |
. | miembros de la estructura de acceso | lexp.nombre_miembro | lexp | LR | No |
-> | miembro puntero de estructura de acceso | rexp->nombre_miembro | lexp | LR | No |
++ | incremento de sufijo | lex ++ | reexp | LR | No |
-- | decremento del sufijo | lex-- | reexp | LR | No |
! | inversa lógica | ! reexp | reexp | rl | No |
~ | inversión bit a bit | ~ reexp | reexp | rl | No |
+ | Monocular, que indica un valor positivo. | + reexp | reexp | rl | No |
- | Monocular, que representa un valor negativo. | - reexp | reexp | rl | No |
++ | incremento de prefijo | ++ lex | reexp | rl | No |
-- | disminución del prefijo | -- lex | reexp | rl | No |
* | acceso indirecto | * reexp | lexp | rl | No |
& | tomar dirección | & lexp | reexp | rl | No |
tamaño de | Tome su longitud, expresada en bytes. |
tamaño de reexp tamaño de (tipo ) |
reexp | rl | No |
( tipo) |
conversión de tipo | (tipo) rexp | reexp | rl | No |
* | multiplicación | rexp * rexp | reexp | LR | No |
/ | división | rexp/rexp | reexp | LR | No |
% | Resto entero | reexp % reexp | reexp | LR | No |
+ | suma | rexp + rexp | reexp | LR | No |
- | sustracción | rexp - rexp | reexp | LR | No |
<< | Shift izquierdo | rexp << rexp | reexp | LR | No |
>> | Giro a la derecha | rexp >> rexp | reexp | LR | No |
> | más que el | rexp > rexp | reexp | LR | No |
>= | mayor o igual a | rexp >= rexp | reexp | LR | No |
< | menos que | rexp < rexp | reexp | LR | No |
<= | Menos que o igual a | rexp <= rexp | reexp | LR | No |
operador _ |
describir | ejemplo de uso | tipo de resultado | Combinación | si se debe controlar el orden de evaluación |
== | igual | rexp == rexp | reexp | LR | No |
!= | 不等于 | rexp != rexp | rexp | L-R | 否 |
& | 位与 | rexp & rexp | rexp | L-R | 否 |
^ | 位异或 | rexp ^ rexp | rexp | L-R | 否 |
| | 位或 | rexp | rexp | rexp | L-R | 否 |
&& | 逻辑与 | rexp && rexp | rexp | L-R | 是 |
|| | 逻辑或 | rexp || rexp | rexp | L-R | 是 |
? : | 条件操作符 | rexp ? rexp : rexp | rexp | N/A | 是 |
= | 赋值 | lexp = rexp | rexp | R-L | 否 |
+= | 以...加 | lexp += rexp | rexp | R-L | 否 |
-= | 以...减 | lexp -= rexp | rexp | R-L | 否 |
*= | 以...乘 | lexp *= rexp | rexp | R-L | 否 |
/= | 以...除 | lexp /= rexp | rexp | R-L | 否 |
%= | 以...取模 | lexp %= rexp | rexp | R-L | 否 |
<<= | 以...左移 | lexp <<= rexp | rexp | R-L | 否 |
>>= | 以...右移 | lexp >>= rexp | rexp | R-L | 否 |
&= | 以...与 | lexp &= rexp | rexp | R-L | 否 |
^= | 以...异或 | lexp ^= rexp | rexp | R-L | 否 |
|= | 以...或 | lexp |= rexp | rexp | R-L | 否 |
, | 逗号 | rexp,rexp | rexp | L-R | 是 |
我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在问题
的。
今天的分享到这里就结束啦!谢谢老铁们的阅读,让我们下期再见。