Vielleicht nocheinmal anders erklärt:
Bei Parametern wird generell immer eine KOPIE des Werts übergeben
Dh, wenn du scanf ohne dem & aufrufst (und scanf auch entsprechend programmiert wäre), wäre das ca. folgender Ablauf:
-Du rufst scanf("%i",zahl); auf
-Das Programm legt (ohne das du davon was merkst) eine neue int-Variable an, ich nenn sie mal kopie
-kopie bekommt den Wert von zahl, also einfach "kopie=zahl;"
-scanf liest von der Tastatur was ein und speichert es in kopie
-scanf ist fertig, kopie wird wieder gelöscht.
-In zahl steht noch immer der Wert, der vor scanf drin war. Deine Tastatureingabe ist weg.
In Wirklichkeit ist scanf aber so programmiert, dass es eine Adresse erwartet.
Wenn du wirklich &zahl übergibst, wäre das:
-Du rufst scanf("%i",&zahl); auf
-Das Programm legt (ohne das du davon was merkst) eine neue int-Variable an, ich nenn sie mal kopie
-kopie bekommt die Adresse von zahl, also "kopie=&zahl;"
-scanf liest von der Tastatur was ein, schaut nach welche Adresse in kopie steht und speichert das Eingelesene an diese Adresse im Arbeitspeicher
-scanf ist fertig, kopie (mit der Adresse von zahl als Wert) wird wieder gelöscht.
-In zahl steht jetz der eingelesene Wert. OK.
Wenn du jetzt dieses Adress-erwartende scanf ohne & aufrufst
(Angenommen, vor scanf steht in zahl zB 4 drin)
-Du rufst scanf("%i",zahl); auf
-Das Programm legt (ohne das du davon was merkst) eine neue int-Variable an, ich nenn sie mal kopie
-kopie bekommt den Wert von zahl, also "kopie=zahl;"
-scanf liest von der Tastatur was ein, schaut nach welche Adresse in kopie steht und speichert das Eingelesene an diese Adresse im Arbeitspeicher. Also beim vierten Byte.
-scanf ist fertig, kopie (mit der Adresse von zahl als Wert) wird wieder gelöscht.
-Beim vierten Byte deines Arbeitsspeichers steht die Eingabe; was vorher drin war ist weg.
Bestenfalls bekommst du einen Absturz.
Für den letzten Fall gibts aber vom Betriebssystem eine Sicherung, die verhindert, dass du Adressen überschreibst, die nicht zu dienen Variablen/zu deinem Programm gehören.
Bei 4 würde dein Programm immer abstürzen, weil das Betriebssystem da was dagegen hat.
Man bekommt dann halt keine freundliche Meldung, einfacher gehts das Programm zu killen
Was printf angeht: printf soll den Inhalt der Variablen ja nur ausgeben und daran nichts verändern.
Also reichen ihm Auch die kopie-Werte, die Adressen interressieren die Funktion nicht.
Deshalb auch kein & bei printf.
Zu dem doppelten &&: Theoretisch hast du recht, aber an welche Adressen deine Variablen kommen entscheidet das Betriebssystem. Da hast du selber keinen Einfluss drauf.