Liege ich denn nun richtig mit der Annahme, dass der Datentyp eines Zeigers (mit *) sowie einer Referenz gleich der Variable sein muss? (Der compiler spuckte zumindestens keine Warnung raus)
Vermutlich ja.
Eine Referenz ohne speziellen Datentyp, der referenziert wird, kann es nicht geben. Auch keine Referenz auf nichts, oder eine, deren Ziel sich im Programm-Ablauf ändert. (Das sind all die "Schweinereien", die man mit Zeigern machen kann und die gern zu Problemen führen)
Auch Zeiger sollte man immer als typisierte Zeiger denken (auch wenn es formal einen void* gibt).
int * xp;
kann man auf zwei Arten lesen und verstehen:
a) xp
ist vom Datentyp int*
( ein Zeiger auf int )
b) *xp
ist ein int
Natürlich gibt es Zeiger auf alles, auch auf andere Zeiger, Objekte, oder Arrays.
Wobei Array und Zeiger bei C/C++ sehr eng verwoben sind.
Referenzen machen hauptsächlich Sinn bei der Übergabe von Parametern an eine Funktion, wenn man der keine eigene Kopie eines Werts geben will, sondern direkten Zugriff auf die interessierende Variable selbst. ( Weil diese ein großes Objekt ist, oder weil sie geändert werden soll ) Dieser Parameter kann dann mit der einfachen Syntax behandelt werden, ohne mit Sternchen oder -> hantieren zu müssen.
Viel Spaß noch 
In C++ unter scheiden sich die Datentypen von einem Array mit 10 Elementen von einem Array mit 8 Elementen. Klarer: Die Anzahl der Elemente ist teil des Datentyps.
Dieses subtile Feature verhindert sehr viele böse Zeigerfehlverwendungen.
Lass dich nicht verwirren: Die "Arduino-Sprache" ist zwar C++, aber das merkt der avr-gcc Compiler nichtselten, und solche Fehler werden zur Laufzeit locker falsch ausgeführt.
int pre[10];
int test[10];
int post[10];
void setup() {
for (int i = 0; i < 10; i++)
test[i] = i;
test[10] = 10; // nicht mal eine Warnung mit arduino 1.8.3
test[11] = 11;
Serial.begin(9600);
for (int i = 0; i < 10; i++) {
Serial.print(pre[i]); Serial.print("\t");
Serial.print(test[i]);
Serial.print("\t");Serial.println(post[i]);
}
}
void loop() { }