Questa domanda è rispondente per C ++: Stroustrup, "Design ed Evolution of C ++" discute questo nella sezione 11.6.1, pp. 247-250.
Vi erano obiezioni generali sull'aggiunta di un nuovo operatore. Si aggiungerebbe alla tabella di precedenza già complicata. I membri del gruppo di lavoro pensavano che avrebbe dato solo una minima utilità rispetto ad avere una funzione, e volevano essere in grado di sostituire le proprie funzioni a volte.
Non c'era un buon candidato per un operatore. ^ è esclusivo-o, e ^^ ha invitato la confusione a causa della relazione tra & e | e && e || . ! non era adatto poiché ci sarebbe la naturale tendenza a scrivere != per l'esponenziazione di un valore esistente, e questo era già stato preso. Il migliore disponibile potrebbe essere stato *^ , che a quanto pare a nessuno piaceva davvero.
Stroustrup considera nuovamente ** , ma ha già un significato in C: a**p è a volte a cui p punta a, e char ** c; dichiara c come puntatore al puntatore a char . Introducendo ** come token che significa "dichiarazione di un puntatore a puntatore a", "punta su ciò che la prossima cosa punta a" (se si tratta di un puntatore) o "esponenziazione" (se seguito da un numero) ha causato problemi di precedenza. a/b**p dovrebbe analizzare come a/(b**p) se p fosse un numero, ma (a/b) * *p se p fosse un puntatore, quindi questo dovrebbe essere risolto nel parser.
In altre parole, sarebbe stato possibile, ma avrebbe complicato la tabella delle precedenze e il parser, ed entrambi sono già troppo complicati.
Non conosco la storia di Java; tutto quello che potevo fare sarebbe speculare. Per quanto riguarda C, da dove è iniziato, tutti gli operatori C sono facilmente tradotti in codice assembly, in parte per semplificare il compilatore e in parte per evitare di nascondere funzionalità dispendiose in operatori semplici (il fatto che operator+() e altri potrebbero nascondere grande complessità e prestazioni hits è stata una delle prime lamentele sul C ++).