Histoire des pointeurs
ALGOL
ALGOL-60 est le papa de C et de Pascal. Il n’avait pas de pointeurs explicites mais avait des passage par valeurs VS passage par références VS passage par nom.
En ALGOL-60, par défaut = par référence
procedure Swap(x, y);
integer x, y;
begin integer t;
t := x;
x := y;
y := t;
end
i = 1;
A[1] := 3;
A[2] := 2;
A[3] := 5;
Swap(i, A[i]);
- Le passage par référence fait que :
- avant : A =
3 2 5eti = 1 - après : A =
1 2 5eti = 3
- avant : A =
D’ailleurs, le passage par référence est disponible en Pascal avec var :
procedure Swap(var A, B: Integer);
var
Temp: Integer;
begin
Temp := A;
A := B;
B := Temp;
end;
Le passage par référence n’existe pas en C (on utilise des pointeurs), mais existe en C++ avec des références.
void swap(int& i, int& j)
{
int tmp = i;
i = j;
j = tmp;
}
int x, y;
swap(x, y);
Par valeur
En ALGO-60, on spécifiait explicitement que le passage se fait par valeur.
procedure Swap(x, y);
value x, y;
integer x, y;
begin integer t;
t := x;
x := y;
y := t;
end
i = 1;
A[1] := 3;
A[2] := 2;
A[3] := 5;
Swap(i, A[i]);
- Le passage par valeur fait que rien en change :
- avant : A =
3 2 5eti = 1 - après : A =
3 2 5eti = 1
- avant : A =
En C, tout est passé par valeur.
Passage par nom
ALGOL-60 permet également le passage par nom (call-by-name). Les arguments n’étaient pas évaluées, mais recopier tel quel dans le code de la fonction.
procedure Swap(x, y);
name x, y;
integer x, y;
begin integer t;
t := x;
x := y;
y := t;
end
i = 1;
A[1] := 3;
A[2] := 2;
A[3] := 5;
Swap(i, A[i]);
L’appel devient :
begin integer t;
t := i;
i := A[i];
A[i] := t;
end
Ainsi par passage par nom on a :
- avant : A =
3 2 5eti = 1 - après : A =
3 2 1eti = 3
On est d’accord : le passage par nom est une catastrophe… Il a été abandonné dans d’autres langages. Mais il permettait des choses intéressantes.
Evaluation paresseuse
Son but est l’évaluation paresseuse. Dans le code suivant comme etat = 0, la fonction fonctionCompliquee n’est jamais appelée !
procedure Swap(etat, position, newPositionX);
name positionX;
integer etat, positionX;
begin
if etat = 0 then
positionX = newPositionX;
end
comment ici etat = 0
hero_bouger(etat, positionX, fonctionCompliquee(positionX));
Le cas de Scala
Scala est un langage fonctionnel que l’on compile pour la JVM. Etonnement, il permet l’évaluation par nom. La documentation https://docs.scala-lang.org/tour/by-name-parameters.html motive le passage par nom comme un moyen de créer des boucles personnalisées : par exemple une boucle while.
object Main {
def whileLoop(condition: => Boolean)(body: => Unit): Unit = {
if (condition) {
body
whileLoop(condition)(body)
}
}
def main(args: Array[String]): Unit = {
var i = 3
whileLoop(i > 0) {
println(i)
i -= 1
}
}
}
affiche
3
2
1
Macros VS passage par nom
Attention, les macros remplacent le code avant la compilation. Là, on `remplace’ une variable par une expression à l’exécution. Ainsi, c’est implémenté avec des thunks (en gros, des adresses mémoires vers du code compilé).
https://www.cs.csustan.edu/~mmartin/teaching/CS4100S11/lectures/Algol_Part4.pdf </!–>
Premiers languages avec pointeurs
Harold Lawson (USA) est crédité comme créateur des pointeurs en 1964 pour le langage PL/I (Programming Language One).
Un exemple de code ici : https://www.ibm.com/docs/en/zos/2.4.0?topic=services-pli-example-building-linked-list. On y déclarait un pointeur P comme suit :
DCL P POINTER;
Cf. https://www.ibm.com/docs/en/zos/3.1.0?topic=services-ceegtstget-heap-storage l’allocation mémoire fonctionne comme suit :
CALL CEEGTST ( HEAPID, NBYTES, ADDRSS, FC );
où CEEGTST est le nom du service pour allouer de la mémoire sur un tas. Il y a plusieurs tas : on donne l’ID du tas où on veut allouer dans HEADID. Le paramètre NBYTES indique le nombre d’octets. Le paramètre ADDRSS est modifié avec l’adresse vers la zone allouée. FC reçoit lui le feedback code (est-ce que l’allocation a réussi ? etc.).
Pointeur nul : erreur à 1 000 000 000$
C. A. R. Hoare a dit en 2009 :
I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn’t resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.