Operatori C e conversione del tipo

Operatori C e conversione del tipo

Operatori

Un operatore è un simbolo che rappresenta una particolare operazione che può essere eseguita su alcuni dati. I dati sono chiamati operando. L'operatore opera quindi su un operando. Gli operatori possono essere classificati come "unari", "binari" o "ternari" a seconda del numero di operandi, ovvero uno, due o tre rispettivamente.

  • Espressione unaria :un'espressione unariaT contiene un operando e un operatore unario.
  • Espressione binaria :un'espressione binariaT contiene due operandi separati da un operatore.

Operatori unari

Inceremento unario e operatori binari

L'operatore di incremento unario (++) incrementa il valore dell'operando di 1. Allo stesso modo l'operatore di decremento unario (–) decrementa il valore di 1.

int x = 0;
int p = 10;
x = p++ ; -----------> Result: x = 10
// Now p will have a value 11. (Postfixing)
x = ++p; -----------> Result : x = 12
// Now p will have a value 12. (Prefixing)
p = 11 -----------> p = 11 

Postfixing: Gli operatori unari (incremento o decremento) quando usati dopo la variabile, come in p++, agiscono come un operatore suffisso. Nell'espressione p++, p viene incrementato dopo che il suo valore è stato utilizzato, ovvero assegnato a x.
Prefisso: Gli operatori unari (incremento o decremento) quando utilizzati prima della variabile, come in ++p, agiscono come un operatore di prefisso. L'espressione ++p incrementa p prima che il suo valore sia stato utilizzato, ovvero assegnato a x.

La tabella seguente contiene altri esempi di operatori unari.

Operatore unario più +

L'operatore T+T (più unario) mantiene il valore dell'operando. L'operando può avere qualsiasi tipo aritmetico o tipo di puntatore.

Operatore meno unario

L'operatore T-T (meno unario) nega il valore dell'operando. L'operando può avere qualsiasi tipo aritmetico. Ad esempio, se TqualityT ha il valore T100T, T-qualityT ha il valore T-100T.

Operatore di negazione logica!

L'espressione restituisce il valore 1 (true) se l'operando restituisce 0 e restituisce il valore 0 (false) se l'operando restituisce un valore diverso da zero.

Operatore di negazione bit a bit ~

L'operatore T~T (negazione bit per bit) restituisce il complemento bit per bit dell'operando. Nella rappresentazione binaria del risultato, ogni bit ha il valore opposto dello stesso bit nella rappresentazione binaria dell'operando. L'operando deve avere un tipo integrale. Il risultato ha lo stesso tipo dell'operando ma non è un lvalue.

Supponiamo che TxT rappresenti il ​​valore decimale T5T. La rappresentazione binaria a 16 bit di TxT è:00000000000000101. L'espressione T~xT produce il seguente risultato (rappresentato qui come un numero binario a 16 bit):11111111111111010.

Operatore indirizzo &

L'operatore T&T (indirizzo) restituisce un puntatore al suo operando. Se Tp_to_yT è definito come puntatore a TintT e TyT come TintT, la seguente espressione assegna l'indirizzo della variabile TyT al puntatore Tp_to_yT:

p_to_y = &y;

Operatore indiretto *

L'operatore T*T (indiretto) determina il valore a cui fa riferimento l'operando di tipo puntatore. Se Tp_to_yT è definito come puntatore a TintT e TyT come TintT, le espressioni:

p_to_y = &y;
*p_to_y = 3;

far sì che la variabile TyT riceva il valore T3T.

La dimensione dell'operatore

L'operatore sizeof restituisce il numero di byte che l'operando occupa in memoria. L'operando può essere una variabile, una costante o un qualificatore di tipo di dati.

/* sample program using sizeof operator */
# include <stdio.h>
void main(void)
{
    int sum;
    printf(“%d \n”, sizeof(float));
    printf(“%d \n”, sizeof(sum));
    printf(“%d \n”, sizeof(char));
    printf(“%d \n”, sizeof(‘G’));
}

L'output del programma sopra sarà dipendente dal compilatore. L'operatore sizeof viene generalmente utilizzato per determinare le lunghezze di entità chiamate array e strutture quando le loro dimensioni non sono note. Viene anche utilizzato per allocare memoria dinamicamente durante l'esecuzione del programma.

Operatori binari

Operatori aritmetici

Gli operatori aritmetici binari sono +, -, * e / e l'operatore modulo %. La divisione intera tronca qualsiasi parte frazionaria. L'operatore modulo restituisce il resto della divisione intera. Questo operatore è applicabile solo per numeri interi e non può essere applicato a float o double.

Gli operatori *, / e % hanno tutti la stessa priorità, che è maggiore della priorità dell'addizione binaria (+) e della sottrazione (-). Nel caso di un'espressione contenente gli operatori aventi la stessa precedenza, viene valutata da sinistra a destra. Questa precedenza predefinita può essere ignorata utilizzando una serie di parentesi. Se è presente più di una serie di parentesi, verranno eseguite per prime le parentesi più interne, seguite dalle operazioni all'interno della seconda coppia più interna e così via.

34 + 5 = 39
12 – 7 = 5
15 * 5 = 75
14 / 8 = 1
17 % 6 = 5

Operatori relazionali

Gli operatori relazionali vengono utilizzati per confrontare due operandi per verificare se sono uguali, disuguali o uno è maggiore o minore dell'altro.

Il valore dell'espressione relazionale è di tipo intero ed è 1 se il risultato del confronto è vero e 0 se è falso.

14 > 8      has the value 1, as it is true
34 <= 19      has the value 0, as it is false 

Operatori logici

Gli operatori logici &&(AND), || (OR) consente di combinare due o più espressioni per formare un'unica espressione. Le espressioni che coinvolgono questi operatori vengono valutate da sinistra a destra e la valutazione si interrompe non appena si conosce la verità o la falsità del risultato.

Nota :Tutte le espressioni, che fanno parte di un'espressione composta, potrebbero non essere valutate, quando sono collegate da &&o || operatori.

Operatori bit a bit

Gli operatori bit per bit forniti da C possono essere applicati solo a operandi di tipo char, short, int e long, sia con segno che senza segno.

&     AND
|     OR
^     XOR
~     one's compliment
<<    Shift Left
>>    Shift Right 

E

AND &copierà un po' il risultato se esiste in entrambi gli operandi.

#include<stdio.h>
main()
 {
    unsigned int a = 60; /* 60 = 0011 1100 */
    unsigned int b = 13; /* 13 = 0000 1101 */
    unsigned int c = 0;
 
    c = a & b; /* 12 = 0000 1100 */
}

O

O | copierà un po' se esiste in uno dei due operandi:

#include<stdio.h>
main()
 {
    unsigned int a = 60; /* 60 = 0011 1100 */
    unsigned int b = 13; /* 13 = 0000 1101 */
    unsigned int c = 0;
 
    c = a | b; /* 61 = 0011 1101 */
 } 

XOR

XOR ^ copia il bit se è impostato in un operando (ma non in entrambi):

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

I contenuti di due variabili vengono scambiati senza l'uso di una variabile temporanea.

Complemento di unità

Questo operatore è unario (richiede un operando) e ha l'effetto di "capovolgere" i bit.

#include<stdio.h>
main()
 {
    unsigned int Value=4; /* 4 = 0000 0100 */
    Value = ~ Value; /* 251 = 1111 1011 */
 }

Maiusc sinistro

Il valore dell'operando di sinistra viene spostato a sinistra del numero di bit specificato dall'operando di destra.

#include<stdio.h>
main()
 {
    unsigned int Value=4; /* 4 = 0000 0100 */
    unsigned int Shift=2;
 
    Value = Value << Shift; /* 16 = 0001 0000 */
 
    Value <<= Shift; /* 64 = 0100 0000 */
 
    printf("%d\n", Value); /* Prints 64 */
}

Utilizza variabili senza segno con questi operatori per evitare risultati imprevedibili.

Maiuscole a destra

Il valore dell'operando di sinistra viene spostato a destra del numero di bit specificato dall'operando di destra.

#include <stdio.h>
main()
{
    unsigned int bytes=256; /* 00000000 00000000 00000000 10000000 */
    do
    {
       printf("%3d \n", bytes);
       bytes >>= 1; /* 00000000 00000000 00000000 01000000 */
    } while (bytes);
    return 0;
}

O/P:

256
128
64
32
16
8
4
2
1

Operatore ternario/condizionale

Le espressioni condizionali scritte con l'operatore ternario “?:” forniscono un modo alternativo per scrivere il costrutto condizionale if. Questo operatore accetta tre argomenti.

La sintassi è:

expression1 ? expression2 : expression3

Se expression1 è true (ovvero Value è diverso da zero), il valore restituito sarebbe expression2, altrimenti il ​​valore restituito sarebbe expression3.

int num, res;
scanf(“%d”, &num);
res = ( num >= 0 ? 1 : 0 ); 

res contiene 1 se num è positivo o zero, altrimenti contiene 0.

int big, a, b, c;
big = (a > b ? (a > c 3 : 4) : ( b > c ? 6 : 8 ));

big contiene il più alto di tutti e tre i numeri.

Operatori di assegnazione composti

La maggior parte degli operatori binari come +, * hanno un operatore di assegnazione corrispondente nella forma op=dove op è uno di +, -, *, /, %, &, |, ^. La spiegazione di questi operatori di assegnazione composta è riportata di seguito nella tabella 2.5.

Considera il valore i =15 per tutte le espressioni fornite nella tabella seguente.

Operatore virgola

L'operatore virgola consente di raggruppare due istruzioni dove è prevista una.

Sintassi:

assignment-expression ,assignment-expression

L'operatore virgola ha associatività da sinistra a destra. Due espressioni separate da una virgola vengono valutate da sinistra a destra. L'operando sinistro viene sempre valutato e tutti gli effetti collaterali vengono completati prima che venga valutato l'operando destro.

Considera l'espressione:

e1, e2

Il tipo e il valore dell'espressione sono il tipo e il valore di e2; il risultato della valutazione di e1 viene scartato. Il risultato è un valore l se l'operando corretto è un valore l.

Questo esempio illustra l'operatore virgola:

for ( i = j = 1; i + j < 20; i += i, j-- ); 

In questo esempio, ogni operando della terza espressione dell'istruzione for viene valutato in modo indipendente. Viene valutato per primo l'operando sinistro i +=i; quindi viene valutato l'operando destro, j––.

L'operatore Virgola restituisce il valore dell'operando più a destra.

Utilizzo dell'operatore Virgola:

#include<stdio.h>
main()
{
   int i, j;
   printf("%d",(i = 0, j = 10));
}

Uscita:

10

Utilizzo dell'operatore Virgola:

#include<stdio.h>
main(){
   int i,j,k;
   k = (i = 4, j = 5);
   printf("k = %d",k);
}

Uscita:

k = 5

Precedenza e ordine di valutazione

La gerarchia degli operatori di uso comune è mostrata nella tabella seguente.

In caso di pareggio tra operazioni della stessa priorità vengono valutate in base alla loro associatività. È possibile utilizzare le parentesi per modificare l'ordine della valutazione. Se è presente più di una serie di parentesi, verranno eseguite per prime le parentesi più interne, seguite dalle operazioni all'interno della seconda coppia più interna e così via.

C, come la maggior parte dei linguaggi, non specifica l'ordine in cui vengono valutati gli operandi di un operatore. Allo stesso modo, anche l'ordine in cui vengono valutati gli argomenti della funzione non è specificato. Quindi la dichiarazione

printf(“%d %d\n”, ++n, power(2, n)); /* AVOID */ 

può produrre risultati diversi con compilatori diversi, a seconda che n venga incrementato prima che venga chiamata alimentazione. La soluzione è scrivere:

++n;
printf(“%d %d\n”, n, power(2, n)); 

Digita Conversione

Quando un operatore dispone di operandi di tipo diverso, vengono convertiti in un tipo comune in base a un numero limitato di regole. In generale, le uniche conversioni automatiche sono quelle che convertono un operando "più stretto" in uno "più ampio" senza perdere informazioni, come convertire un intero in un valore a virgola mobile.

Conversioni aritmetiche implicite

Se un operatore binario come +, -, * o / che accetta due operandi di tipo diverso, il tipo "inferiore" viene promosso al tipo "superiore" prima che l'operazione proceda. Il risultato è di tipo “superiore”.

Un'operazione aritmetica tra un intero e un intero produce sempre un risultato intero. L'operazione tra float e float produce sempre un risultato float. L'operazione tra float e intero produce sempre un risultato float.

Digita conversione in Compiti

In alcuni casi il tipo dell'espressione e il tipo della variabile sul lato sinistro dell'operatore di assegnazione potrebbero non essere gli stessi. In tal caso il valore dell'espressione promosso o retrocesso a seconda del tipo di variabile sul lato sinistro dell'operatore =.

int p, iNum = 30;
float b = 3.5;
p = b;
b = iNum; 

Nell'esempio precedente, la prima assegnazione memorizzerà 3 nella variabile p, poiché p è una variabile intera, non può memorizzare un valore float. Il float viene retrocesso a un numero intero e il suo valore viene memorizzato. Nella prossima affermazione accade esattamente il contrario. Qui, 30 viene promosso a 30.000000 e quindi memorizzato in b, poiché b è una variabile float.

Tipo casting

Le conversioni di tipo esplicite possono essere forzate in qualsiasi espressione, con un operatore unario chiamato cast. Nella costruzione:

(type-name) expression

L'espressione viene convertita nel tipo denominato dalle regole di conversione. Il significato preciso di un cast è come se l'espressione fosse assegnata a una variabile del tipo specificato, che viene poi utilizzata al posto dell'intera costruzione.

int iCount;
float fVal = 34.8f;
iCount = (int) fVal; /* iCount contains 34 */