Seja diligente e encoraje os anos a não esperar por ninguém
Desenvolvimento de jogos C/C++
Olá, aqui é Junxi_, eu estava muito ocupado há alguns dias e não tive tempo de atualizar, e agora finalmente estou livre. Este é o segundo artigo da atualização explosiva do fígado de hoje e também é o último artigo do nosso [C Language Elementary] para levá-lo a brincar com todos os operadores comumente usados facilmente. Não vamos falar bobagem, vamos direto ao ponto
- Antes do início oficial, ainda usamos um mapa mental para ajudar a relembrar brevemente o conteúdo básico dos operadores
- Vamos para a última parte
Explicação detalhada dos operadores 4
1. Referências de subscrito, chamadas de função e membros de estrutura
1. [ ] operador de referência de subscrito
O operando deste operador: um nome de array + um valor de índice
int arr[10];//Cria um array
arr[9] = 10;//Prático operador de referência de subscrito.
Os dois operandos de [ ] são arr e 9.
- Observe aqui que arr e 9 são apenas dois operandos de "[]", então também podemos escrever o array assim:
9[arr];
- O código da prova é o seguinte:
int main()
{
int arr[10] = {
1,2,3,4,5 };//不完全初始化,此时后面未初始化元为0
//
//数组的起始是有下标的,下标是0开始的
printf("%d\n", arr[2]);//[] 下标引用操作符,arr 和 2 是[] 的两个操作数
printf("%d\n", 2[arr]);
return 0;
}
- Mas geralmente para a legibilidade e fluência do código, é melhor não escrever assim, aqui está apenas para dizer que é correto escrever assim!
2. ( ) operador de chamada de função
- Aceita um ou mais operandos: o primeiro operando é o nome da função e os demais operandos são os parâmetros passados para a função.
#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;
}
- É muito simples e você já viu isso muitas vezes em sua vida diária, então não vou entrar em detalhes aqui.
3. Acessando membros de uma estrutura
- Normalmente existem duas formas
. 结构体.成员名
-> 结构体指针->成员名
"." Estrutura. Nome do membro
-
这种通常用于直接访问结构体成员
struct Book
{
char name[30];//成员
char author[20];
float price;
};
int main()
{
struct Book b1 = {
"C语言", "zz",99.6f };
struct Book b2 = {
"数据结构","yy",88.6f};//书
printf("%s %s %.1f\n", b1.name, b1.author, b1.price);
printf("%s %s %.1f\n", b2.name, b2.author, b2.price);
//结构体变量.成员名
return 0;
}
-> ponteiro de estrutura -> nome do membro
主要用于在结构体传参时通过结构体指针找到对应结构体成员
- código mostra como abaixo:
struct Book
{
char name[30];//成员
char author[20];
float price;
};
void Print(struct Book * p)
{
printf("%s %s %.1f\n", (*p).name, (*p).author, (*p).price);
printf("%s %s %.1f\n", p->name, p->author, p->price);
//->
//结构指针->成员名
}
int main()
{
struct Book b1 = {
"C语言", "zz",99.6f };
struct Book b2 = {
"数据结构","yy",88.6f};//书
Print(&b1);
Print(&b2);
//printf("%s %s %.1f\n", b1.name, b1.author, b1.price);
//printf("%s %s %.1f\n", b2.name, b2.author, b2.price);
//结构体变量.成员名
return 0;
}
2. Avaliação da expressão
- A ordem na qual as expressões são avaliadas é determinada em parte pela precedência e associatividade dos operadores.
Da mesma forma, os operandos de algumas expressões podem precisar ser convertidos em outros tipos durante a avaliação
1. Conversão implícita de tipo
- As operações aritméticas inteiras de C são sempre
以缺省整型类型的精度
executadas por pelo menos . - Para obter essa precisão,Operandos de caractere e inteiro curto em expressões são convertidos em tipos inteiros normais antes do uso, essa conversão é chamada de promoção de inteiro.
- Significado da promoção inteira:
- A operação de número inteiro da expressão deve ser executada no dispositivo de operação correspondente da CPU. O comprimento do byte do operando da unidade aritmética inteira (ALU) na CPU é geralmente o comprimento do byte de int e também é o comprimento do registrador de uso geral da CPU.
- Portanto, mesmo que os dados de dois tipos de caracteres sejam adicionados, eles devem primeiro ser convertidos para o comprimento padrão do operando inteiro na CPU quando a CPU executa .
- É difícil para uma CPU de uso geral (CPU de uso geral) adicionar diretamente dois bytes de dados de 8 bits (embora possa haver tais instruções de adição de byte em instruções de máquina). Portanto, os vários valores inteiros na expressão cujo comprimento pode ser menor que o comprimento de int devem ser convertidos em int ou unsigned int antes de serem enviados à CPU para cálculo.
//实例1
char a,b,c;
...
a = b + c;
- Os valores de b e c são promovidos a inteiros normais antes que a operação de adição seja realizada.
Após a conclusão da operação de adição, o resultado é truncado antes de ser armazenado em a.
Como realizar a melhoria geral?
- A promoção de inteiro é promovida de acordo com o bit de sinal do tipo de dados da variável
- O código de exemplo é o seguinte:
//负数的整形提升
char c1 = -1;
变量c1的二进制位(补码)中只有8个比特位:
1111111
因为 char 为有符号的 char
所以整形提升的时候,高位补充符号位,即为1
提升之后的结果是:
11111111111111111111111111111111
//正数的整形提升
char c2 = 1;
变量c2的二进制位(补码)中只有8个比特位:
00000001
因为 char 为有符号的 char
所以整形提升的时候,高位补充符号位,即为0
提升之后的结果是:
00000000000000000000000000000001
//无符号整形提升,高位补0
- Exemplos de reforços de plástico:
//实例1
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;
}
- No exemplo 1, a e b precisam ser melhorados, mas c não precisa ser melhorado
- Depois que a e b são promovidos plasticamente, eles se tornam números negativos, então o resultado da expressão a== 0xb6, b == 0xb600 é falso, mas se c não sofre promoção plástica, o resultado da expressão c==0xb6000000 é verdadeiro.
//实例2
int main()
{
char c = 1;
printf("%u\n", sizeof(c));
printf("%u\n", sizeof(+c));
printf("%u\n", sizeof(-c));//%u - 10进制的形式打印无符号的整数
return 0;
}
- No exemplo 2, desde que c participe da operação de expressão, a promoção de número inteiro ocorrerá e a expressão +c será promovida, então sizeof(+c) é 4 bytes.
- A expressão -c também sofre promoção plástica, então sizeof(-c) é 4 bytes, mas sizeof(c) é 1 byte.
2. Conversão aritmética
- Se os operandos de um operador forem de tipos diferentes, a operação não poderá prosseguir a menos que um dos operandos seja convertido para o tipo do outro .
- A seguinte hierarquia é chamada de conversão aritmética ordinária
long double
double
float
unsigned long int
long int
unsigned int
int
acima digite de alto -> baixo
- Se o tipo de um operando for inferior na lista acima, ele deve primeiro ser convertido para o tipo do outro operando antes de realizar a operação
- Perceber:
A conversão aritmética deve ser razoável, caso contrário, haverá alguns problemas potenciais
float f = 3.14;
int num = f;//隐式转换,会有精度丢失
3 Propriedades dos operadores
- Existem três fatores que afetam a avaliação de expressões complexas.
1. 操作符的优先级
2. 操作符的结合性
3. 是否控制求值顺序。
- Qual dos dois operadores adjacentes é executado primeiro? Depende de suas prioridades. Se ambos tiverem a mesma prioridade, depende de sua associatividade.
- operador precedente
Algumas expressões com problemas
- exemplo um
//表达式的求值部分由操作符的优先级决定。
//表达式1
a*b + c*d + e*f
Notas:代码1在计算的时候,由于*比+的优先级高,只能保证,*的计算是比+早,但是优先级并不能决定第三个*比第一个+早执行。
- Portanto, a ordem das expressões do computador pode ser:
a*b
c*d
a*b + c*d
e*f
a*b + c*d + e*f
或者:
a*b
c*d
e*f
a*b + c*d
a*b + c*d + e*f
- Exemplo 2
//表达式2
c + --c;
Notas:同上,操作符的优先级只能决定自减--的运算在+的运算的前面,但是我们并没有办法得知,+操作符的左操作数的获取在右操作数之前还是之后求值,所以结果是不可预测的,是有歧义的。
- Exemplo três
int fun()
{
static int count = 1;
return ++count;
}
int main()
{
int answer;
answer = fun() - fun() * fun();
printf( "%d\n", answer);//输出多少?
return 0;
}
- Embora os resultados sejam os mesmos na maioria dos compiladores.
- Mas no código acima responda = fun() - fun() * fun(); só podemos saber pela prioridade do operador: primeiro calcule a multiplicação, depois calcule a subtração.
- A ordem na qual as funções são chamadas não pode ser determinada pela precedência dos operadores.
- Exemplo quatro
#include <stdio.h>
int main()
{
int i = 1;
int ret = (++i) + (++i) + (++i);
printf("%d\n", ret);
printf("%d\n", i);
return 0;
}
//尝试在linux 环境gcc编译器,VS2013环境下都执行,看结果。
-
O resultado do ambiente Linux:
-
O resultado do ambiente VS2013:
-
Veja o mesmo código produz resultados diferentes, por quê?
-
Quando o primeiro + neste código é executado, se o terceiro ++ é executado é incerto, porque a ordem do primeiro + e do terceiro ++ anterior não pode ser determinada dependendo da prioridade e associatividade dos operadores.
Resumo:
Se a expressão que escrevemos não pode determinar o único caminho de cálculo através dos atributos do operador, então há um problema com esta expressão!
- Referência de dados:
A imagem da prioridade do operador no blog foi retirada deste blog:
Explicação detalhada: prioridade do operador
Resumir
- O conteúdo de hoje termina aqui por enquanto, e terminamos todos os pontos de conhecimento e pontos propensos a erros sobre os operadores hoje. Se você ainda tiver dúvidas, você mesmo deve tentar, caso contrário, é muito fácil esquecer só de olhar, e temos que praticar repetidamente para nos familiarizarmos!
- Acima está todo o conteúdo sobre operadores. Descrevemos o conteúdo desta parte em quatro capítulos. Se você estiver interessado, pode ler os capítulos relevantes anteriores. Vou postar o link aqui!
[C Language Elementary] Leva você a jogar facilmente com todos os operadores comumente usados (1) - operador aritmético, operador de deslocamento,
operador
de bit - Bem, se tiverem alguma dúvida, perguntem-me na área de comentários ou mensagem privada, até à próxima!
Não é fácil para um novo blogueiro criar. Se você acha que o conteúdo do artigo é útil para você, clique neste novo blogueiro antes de sair. Seu apoio é minha motivação para atualizar! ! !
**(Ke Li pede para você apoiar o blogueiro três vezes seguidas!!! Clique no comentário abaixo para curtir e coletar para ajudar Ke Li)**