Bienvenue sur PEBKAC.fr, le site qui recense les anecdotes où l’on se moque des utilisateurs ne maîtrisant pas l’outil informatique. PEBKAC est un acronyme signifiant « Problem Exists Between Keyboard And Chair ».
Le problème se situe entre la chaise et le clavier : soumettez vos histoires, donnez votre avis !
Ce site n'est pas le site original pebkac.fr. Je publie ici la liste des PEBKAC que j'ai pu sauvegarder avant que le site original ne soit mis hors ligne.
Toujours le même professeur d'informatique. Ce cours-ci, il a expliqué et soutenu, malgré les protestations et contre-exemples du peu qui connaissent un peu la programmation dans notre classe, qu'une fonction modifiait les valeurs des variables que l'on passe en paramètre.
Je ne vois pas autre chose à dire qu'une fois de plus : PEBKAC.
PEBKAC #9081 proposé par Dorni le 10/12/2013 | 47 commentaires | 👍🏽 👎🏽 -231
Passage de pointeurs ?
Commentaire #121796 écrit par Epok__ le 10/12/2013 à 08h40 | 👍🏽 👎🏽
Ca peut etre le cas , ca sert pas qu'a faire de l'affichage . Remplir une matrice 15*15 ou realloc dynamiquement c'est moche de mettre 10-15lignes dans le code a chaque fois
Commentaire #121800 écrit par Alaff le 10/12/2013 à 08h51 | 👍🏽 👎🏽
Y a pas que le passage par valeur dans la vie. Passage par références, pointeurs... Une variable peut aussi être un tableau, etc.
Et heureusement ! Sinon on serait quand même super limités...
Bref, CTLP
Commentaire #121801 écrit par Limeila le 10/12/2013 à 08h57 | 👍🏽 👎🏽
Techniquement, la valeur que tu passes est une adresse. Tu peux modifier la variable qui s'y trouve, mais ce n'est pas vraiment elle qui a été passé en paramètre. J'hésiterais donc à réprimander Dorni sur cette base. Mais bon... ça reste une question de français plus que de programmation.

Ce qui est malheureux, c'est qu'on ignore de quel langage il est question ici. Dans ceux que je connais, une valeur passée en paramètre se verra copié sur la pile et une modification de la copie elle-même (et non ce vers quoi elle peut pointer) n'aura donc pas d'incidence sur la valeur originale. Mais est-ce toujours le cas? C'est une question qui mérite d'être posée et je ne serais pas prêt à parier sur la réponse. Même en C/C++ il faut réfléchir un peu. D'après-vous, qu'arrive-t-il si on "inline" une fonction? La copie se fait-elle quand même? Si elle ne se faisait pas et que le paramètre était modifié, la modification serait fait sur la valeur originale elle-même! Mais n'ayez crainte, une fonction, même marquée "inline" par le programmeur, ne sera jamais "inlinée" par le compilateur si un paramètre est modifié.
Commentaire #121803 écrit par FlashSoul le 10/12/2013 à 09h01 | 👍🏽 👎🏽
surtout que tu précises même pas de quel langage il s'agit
Commentaire #121806 écrit par yomama le 10/12/2013 à 09h19 | 👍🏽 👎🏽
Nan mais ça peut, mais en général ce n'est pas le cas.

Perso je pense naïvement au PHP étant donné que c'est ce que j'utilise le plus : il y a une syntaxe spécifique pour passer des variables par référence à une fonction, laquelle peut donc réellement agir sur les emplacements mémoires représentés par ces variables. Mais de base, c'est un comportement "traditionnel" : les variables passées à la fonction sont "copiées" en tant qu'arguments de cette dernière (mon explication sucks un peu techniquement mais vous voyez le truc).

(Je précise pour la postérité que cette distinction s'effectue dans la déclaration de la fonction en question, et pas dans son appel, chose qu'on pouvait faire avant mais qui est dépréciée depuis quelques versions mineures.)
Commentaire #121810 écrit par neemzy le 10/12/2013 à 09h28 | 👍🏽 👎🏽
Effectivement, en VB.Net tu peux passer un paramètre ByVal ou ByRef, en C# tu peux préciser ref ou out sur un paramètre, etc...
Commentaire #121811 écrit par Shadam le 10/12/2013 à 09h29 | 👍🏽 👎🏽
Ça dépend du langage.
CTLP.
Commentaire #121812 écrit par Bilgetz le 10/12/2013 à 09h35 | 👍🏽 👎🏽
Il a raison, BEDP.
Vous evoquez les pointeurs et autres passages par référence, donc la valeur (de la référence ou du pointeur) passée à la fonction n'est pas modifiée.

M'enfin, ici comme en tout, il y a plusieurs points de vue possibles.
Commentaire #121814 écrit par dunpointdevuesemantique le 10/12/2013 à 09h42 | 👍🏽 👎🏽
Tel que c'est écrit, le prof soutient que TOUT passage de paramètre se fait par référence.
Donc BEDP.
Commentaire #121815 écrit par mini le 10/12/2013 à 09h46 | 👍🏽 👎🏽
Et si on veut être vicieux, on peut parler de Java où les paramètres des méthodes sont systématiquement passés par valeur. Mais comme on ne manipule pas les objets directement comme on pourrait le penser naïvement quand on découvre le langage, mais par référence, les objets eux-mêmes peuvent être modifiés.

Extraits de http://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html :

Primitive arguments, such as an int or a double, are passed into methods by value. This means that any changes to the values of the parameters exist only within the scope of the method. When the method returns, the parameters are gone and any changes to them are lost.

Reference data type parameters, such as objects, are also passed into methods by value. This means that when the method returns, the passed-in reference still references the same object as before. However, the values of the object's fields can be changed in the method, if they have the proper access level.
Commentaire #121816 écrit par Acné le 10/12/2013 à 09h57 | 👍🏽 👎🏽
"qu'une fonction modifiait les valeurs des variables que l'on passe en paramètre."
Ça pouvait être une fonction ou un langage en particulier... vu que ce PEBKAC manque de précision on devrait accorder le bénéfice du doute au prof.
Commentaire #121819 écrit par aDev le 10/12/2013 à 10h14 | 👍🏽 👎🏽
Je renchéris, ce serait bien de savoir de quoi on parle ici !
Commentaire #121820 écrit par aDev le 10/12/2013 à 10h15 | 👍🏽 👎🏽
Le problème c'est que le langage n'est pas précisé dans le PEBKAC. En général les deux modes sont possibles (passage par valeur ou référence), mais je ne serais pas étonné qu'il en existe qui passent tout par référence. Ou alors qui passeraient les paramètres par référence si rien n'est précisé, le COBOL par exemple le fait.
Commentaire #121822 écrit par Acorah le 10/12/2013 à 10h21 | 👍🏽 👎🏽
Idem, c'est un peu vague. Impossible de voter BEDP ou CTLP.
Commentaire #121825 écrit par Youplà le 10/12/2013 à 10h34 | 👍🏽 👎🏽
Ben, elle modifie la valeurs si la variable et pointé CTLP, de plus sur certain système (wlanguage ...) la variable est pointé par défaut, il faut donc précisé l'inverse à savoir quel est local.
Commentaire #121827 écrit par imanoka le 10/12/2013 à 10h39 | 👍🏽 👎🏽
cela dépend complètement du langage utilisé, sans autres précisions on est obligé de dire qu'elle est modifiable , pas nécessairement modifié mais pour le coup CTLP
Commentaire #121831 écrit par Kototsu le 10/12/2013 à 10h51 | 👍🏽 👎🏽
Vous omettez le passage sur les contre-exemples.
Commentaire #121832 écrit par mini le 10/12/2013 à 10h58 | 👍🏽 👎🏽
En php les objets sont passés par référence, pour les valeurs il faut mettre un & devant le nom de la variable si on veut la passer par référence.
Commentaire #121835 écrit par Geekimo le 10/12/2013 à 11h09 | 👍🏽 👎🏽
Bande de moi, va !
Commentaire #121837 écrit par chipeauteur le 10/12/2013 à 11h22 | 👍🏽 👎🏽
Certes, un bon contre-exemple invalide un argument. Mais là nous n'avons pas d'exemples de ces contre-exemples, on ne peut pas juger.

EDIT: de plus rien ne précise que le langage appris est connu des étudiants.
Commentaire #121843 écrit par aDev le 10/12/2013 à 11h36 | 👍🏽 👎🏽
En C# si tu passes un objet "maison" en paramètre il est forcément par référence, tu pointes vers le même emplacement mémoire, donc si tu le modifies dans l'appelée, l'appelant le récupère modifié.
Seul les types primitifs doivent être précisé ref (même emplacement mémoire) ou out (l'appelé doit modifier la valeur) pour être pris par référence.
Commentaire #121844 écrit par Shadam le 10/12/2013 à 11h36 | 👍🏽 👎🏽
Mais le problème que vous posez vaut pour tout PEBKAC.
Tout PEBKAC peut être remis en cause avec un contexte et des paramètres inconnus ou peu clairs.

Or, il me semblait que l'on considérait l'auteur comme la personne ayant raison par défaut, sauf preuve manifeste du contraire. Ce qui n'est pas le cas ici.
Commentaire #121847 écrit par mini le 10/12/2013 à 12h23 | 👍🏽 👎🏽
Pas mal de langages "recents" font du passage par reference :
- Java
- Python
- ...
Commentaire #121866 écrit par Matthieu le 10/12/2013 à 13h36 | 👍🏽 👎🏽
Je suis d'accord avec toi, mais dans le cas présent, je maintiens qu'il manque des éléments pour voter.

"Ce cours-ci, il a expliqué et soutenu [...] qu'une fonction modifiait [toujours] les valeurs des variables que l'on passe en paramètre" m'aurait clairement fait pencher du côté du BEDP.

À un mot près c'est dommage... Et je veux bien être considéré comme tatillon mais je ne serais pas le seul à plonger !
Commentaire #121889 écrit par aDev le 10/12/2013 à 16h07 | 👍🏽 👎🏽
Bon ok, je ne suis pas programmeur, mais le passage par référence je l'ai vu dans à peu prêt tous les langages que j'ai cotoyé (PHP, C, PowerShell, ptet C++ et Perl là je ne me souviens plus).
Et je ne vois pas comment l'expliquer autrement que la fonction modifie la variable qui lui est passée en référence (car on lui passe bien la référence/pointeur/adresse d'une variable externe à la fonction, donc on modifie son contenu soit la valeur de la variable).

D'ailleurs, sur les sites des éditeurs de ces langages (enfin pour PHP et PowerShell), c'est toujours expliqué comme ça.
Exemple : http://php.net/manual/fr/language.references.pass.php

Donc je valide l'explication du prof, mais il est vrai que ce n'est valable QUE dans ce cas présent, et qu'il ne faut pas le généraliser.
Commentaire #121893 écrit par Woofy le 10/12/2013 à 16h37 | 👍🏽 👎🏽
passage par référence en C?? Oo
Commentaire #121894 écrit par yomama le 10/12/2013 à 17h18 | 👍🏽 👎🏽
point soumis à controverse :
http://javadude.com/articles/passbyvalue.htm
Commentaire #121895 écrit par yomama le 10/12/2013 à 17h20 | 👍🏽 👎🏽
Je ne suis pas programmeur, je le répète. On appelle ça un passage par référence en PHP. En C, ça doit être le passage par pointeur ou quelque chose dans le genre, appelez-le comme vous voulez je ne suis pas pointilleux là dessus, mais au final ça reviens au même dans l'utilisation qui en est faite : on modifie la valeur d'une variable créée et utilisée à l'extérieur de la fonction.
Commentaire #121896 écrit par Woofy le 10/12/2013 à 17h29 | 👍🏽 👎🏽
Effectivement ca depends du language et du mode de passage de parametre (reference,pointeur). Soit vous etes tous les deux des pebkac,soit aucun des deux (il faut etre moins categorique)
Commentaire #121942 écrit par grinchet le 10/12/2013 à 19h07 | 👍🏽 👎🏽
En java, on ne passe en argument que des type canoniques (immutables) ou des references (immutables aussi) vers de objets.
Donc, on ne peut pas modifier un parametre. Par contre, dans le cas des references, on peut modifier l'objet pointé par la reference si il est mutable, ce qui peut revenir a modifier le parametre.
Commentaire #121944 écrit par grinch le 10/12/2013 à 19h14 | 👍🏽 👎🏽
@Yomama :
#include <stdio.h>
 
 void fontionQuiTue(int *a){
         (*a)++;
 }
 
 int main(int argc,char ** argv){
         int a=2;
         fontionQuiTue(&a);  // Je crois que ça s'appelle passage par référence.
         printf("Magie %d/n",a);
         return 0;
 }

fuck les commentaires n'affichent pas les étoiles. Désolé pour l'hérésie du commentaire en C++.
Commentaire #121951 écrit par but2ene le 10/12/2013 à 19h46 | 👍🏽 👎🏽
Bof aucune controverse, que des noob</troll>. C'est juste que la valeur des objets (ceux créé avec new) est une adresse mémoire contrairement au type primitif. Donc toujours par référence pointeur pour les objet et par valeur pour les type primitif (int,char, byte,...).
Commentaire #121954 écrit par but2ene le 10/12/2013 à 19h59 | 👍🏽 👎🏽
Non, Java passe toujours les variables par valeur...

Néanmoins, en interne, le compilateur JIT effectue les optimisations dynamiquement, et si possible passe l'information par référence pour gagner de la vitesse.
Commentaire #121955 écrit par OzoneGrif le 10/12/2013 à 20h04 | 👍🏽 👎🏽
Je me lève je confirme et je sors.
Commentaire #121956 écrit par but2ene le 10/12/2013 à 20h05 | 👍🏽 👎🏽
Sinon en prolog c'est toujours vrai.
Commentaire #121958 écrit par but2ene le 10/12/2013 à 20h05 | 👍🏽 👎🏽
Dans les langages récents comme Java ou C# , la notion de passage par référence ou valeur n'a pas beaucoup de sens. On considère toujours que le passage s'effectue par valeur. C'est à dire que la variable reste locale et n'affecte jamais la variable utilisée par l'appel.

Quand on passe un objet, on passe une copie du pointeur de cet objet. Si dans ta fonction tu fais A = new MyObj(), tu n'effaces pas ton objet source, il est toujours là, donc c'est un passage par valeur.
Commentaire #121960 écrit par OzoneGrif le 10/12/2013 à 20h13 | 👍🏽 👎🏽
mh pourquoi pas, j'aurais tendance à appeler ça un passage par valeur d'un pointeur.

Parce que le passage par référence introduit par le c++ (qui n'existe pas en c) cohabite avec ce que tu montres:

#include <stdio.h>
 
 void fonctionQuiTue_pointeur(int *a) {
     (*a)++;
 }
 
 void fonctionQuiTue_reference(int &a){
     a++;
 }
 
 int main(int argc, char ** argv){
     int a=2;
     fonctionQuiTue_pointeur(&a);
     printf("Magie %d/n", a);
     
     fonctionQuiTue_reference(a);
     printf("Magie encore plus %d/n",a);
 
 }


dans l'exemple précédent, je considère que fonctionQuiTue_pointeur prend son paramètre par valeur, paramètre qui est un pointeur : dans main, je ne passe pas a mais l'adresse de a, ladite adresse est copiée dans le pointeur a de fonctionQuiTue_pointer : passage par valeur.

fonctionQuiTue_reference, utilise le mécanisme de référence du C++ qui n'existe pas en C, et prend bel et bien son paramètre par référence : dans main je lui donne a.

(oui je sais printf c'est C et pas C++, c'était pour l'exemple)
Commentaire #121970 écrit par yomama le 10/12/2013 à 21h14 | 👍🏽 👎🏽
Euh... non !

En Java, lorsqu'on passe un paramètre à une méthode, il est passé par valeur sur la pile. Au retour de la méthode, si un paramètre passé était tiré d'une variable, elle possède toujours l'ancienne valeur.

Mais cela ne veut pas dire qu'on ne peut pas changer le contenu de la variable qui contient la valeur du paramètre passé au début de la méthode. Ce n'est pas une pratique conseillée, il est souvent suggéré de déclarer les variables utilisées pour les paramètres dans une signature de méthode en final, mais il ne s'agit en rien d'une obligation.

Je crois que tu confonds passage par valeur (la valeur est recopiée, donc il n'est pas possible d'impacter le contexte lors de l'appel) et les variables déclarées immuables (avec le mot-clef final).

En revanche, je suis d'accord avec toi (et je l'avais précisé dans mon message) : il est possible de modifier un objet référencé. Mais bon, juste pour pinailler, il n'est pas nécessaire que l'objet soit modifiable pour le modifier... Si le security manager laisse passer l'appel à AccessibleObject.setAccessible(boolean), il est possible de changer même un attribut privé dans un objet.

Bon, il est tard et je ne suis pas sûr d'être très clair... J'espère cependant avoir contribué à une meilleure compréhension du fonctionnement.
Commentaire #121975 écrit par Acné le 10/12/2013 à 23h57 | 👍🏽 👎🏽
C'est un pebkac vachement mal posé quand même

- On connait pas le langage source
- Le prof voulait-il dire "une fonction modifie toujours les variables passés en paramètre" (dans ce cas c'est un gros pebkac) ou bien "une fonction PEUT modifier les variables en paramètres si ils sont passés par référence"(dans ce cas c'est toi le pebkac)????

Des précisions boudiou, on peut pas juger sinon!

Edit : Mais d'usage, pour les puristes, une fonction n'est pas censée modifier les paramètres (c'est quand même abbérant quand on y pense de toutes façons), c'est plutôt le rôle des procédures de faire cela.
Commentaire #121981 écrit par Sonny le 11/12/2013 à 00h56 | 👍🏽 👎🏽
Exact ! Merci pour la précision :)
Commentaire #121996 écrit par neemzy le 11/12/2013 à 09h40 | 👍🏽 👎🏽
Oups, effectivement il manque un peu de précisions ici.
Le langage, c'est du Python, et le prof voulait dire que la fonction modifiait toujours les variables passées en paramètres (variables de type int).
Edit :
Du coup nos codes ressemblent à ça :
def fonction1(x,y,z):
    aux_x_fonction1=x
    aux_y_fonction1=y
    aux_z_fonction1=z
   ...
Commentaire #122091 écrit par Dorni le 11/12/2013 à 16h52 | 👍🏽 👎🏽
Bouuh, effectivement, c'est très laid :D
Dommage que cette précision manque dans le PEBKAC, il aurait été mieux apprécié.
Commentaire #122132 écrit par OzoneGrif le 11/12/2013 à 18h48 | 👍🏽 👎🏽
Beaucoup de langages (voir, la majorité d'entre eux) ne font pas de différence entre une fonction et une procédure. En fait, beaucoup argüeront qu'il n'y a pas de réelle différence entre les deux concepts.

Mais Il est vrai que le pebkac manque cruellement de précision.
Commentaire #122265 écrit par Aralicia le 12/12/2013 à 13h25 | 👍🏽 👎🏽
D'ac-cord... ~_~
Bon je sais quoi voter à présent.
Commentaire #122289 écrit par Youplà le 12/12/2013 à 15h56 | 👍🏽 👎🏽
J'ai bien parlé de purisme :)
Commentaire #122330 écrit par Sonny le 12/12/2013 à 20h22 | 👍🏽 👎🏽
Ah quand même! Alors oui ton prof est un putain de pebkac!!!
Commentaire #122331 écrit par Sonny le 12/12/2013 à 20h23 | 👍🏽 👎🏽