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.
Quand j'étais jeune, il y a quelques siècles, j'avais relu le code d'un copain qui voulait se faire une implémentation DIY de listes en C.

Pour contourner le problème de la déclaration du type des éléments de la liste (pour que newlist(char) crée une liste de char, newlist(double) une liste de double), il avait mis en place une pseudo-fonction dans les directives de préprocesseur. Et comme il avait un TOC sur les ternaires, il n'avait utilisé que ça, pour six types de variables (char, short, int, long, float, double).

Je n'ai pas souvent eu peur devant du code. Jamais, en fait. Excepté devant :

# TYPE(a) = (a == "char" || a == "short" || a == "int") ? (( a == "char") ? char : (a == "short") ? short : int) : ((a == "long") ? long : (a == "float") ? float : double)

M'étant enfui en courant, je n'ai jamais su si ça fonctionnait. Où est rangé le PROZAC ?... PEBKAC.
PEBKAC #7524 proposé par Geist le 10/04/2013 | 32 commentaires | 👍🏽 👎🏽 +146
._.

En gros, il essaye d'assigner plusieurs types de variables en même temps pour une seule variable?
Commentaire #88173 écrit par ROB le 10/04/2013 à 12h43 | 👍🏽 👎🏽
Le PROZAC c'était il y a 10 jours, du va devoir patienter jusqu'à l'année prochaine.
Commentaire #88175 écrit par Link le 10/04/2013 à 12h49 | 👍🏽 👎🏽
Une macro C c'est souvent sale.
Commentaire #88176 écrit par Gwirk le 10/04/2013 à 12h50 | 👍🏽 👎🏽
Je... j'ai des nausées là @_@

(mais quelle idée d'emboiter 5 ternaire sur une ligne ?)
Commentaire #88178 écrit par blag le 10/04/2013 à 12h52 | 👍🏽 👎🏽
A ce point là ? Il est possible d'utiliser des tests conditionnels autre que le test ternaire...
Commentaire #88181 écrit par Epok__ le 10/04/2013 à 13h00 | 👍🏽 👎🏽
Merci de confirmer que j'avais bien compris. Du coup je vais pouvoir voter.
Commentaire #88182 écrit par FunnyD le 10/04/2013 à 13h00 | 👍🏽 👎🏽
C'est magnifique ! C'est juste quelqu'un qui aime se lancer des défis... ^_^

"Voyons si le jour où j'aurai un problème, je serai capable de debug ce bidule !"
Commentaire #88184 écrit par Alibi le 10/04/2013 à 13h01 | 👍🏽 👎🏽
Capitaine Obvious, j'ai besoin de toi ! J'ai pas pigé le code !
Commentaire #88199 écrit par qwerty le 10/04/2013 à 13h42 | 👍🏽 👎🏽
Je pense que c'est justement pour faire tenir le tout sur une seule ligne.
Commentaire #88203 écrit par juu le 10/04/2013 à 13h56 | 👍🏽 👎🏽
Je sais pas, moi ça me paraît pas si illisible...

# TYPE(a) = (a == "char" || a == "short" || a == "int") ? (( a == "char") ? char : (a == "short") ? short : int) : ((a == "long") ? long : (a == "float") ? float : double)

//premier test, pour savoir si c'est un char, un short ou un int :
 (a == "char" || a == "short" || a == "int") ?
 //... puis on traite cas par cas :
 //si c'est char :
 (( a == "char") ? char
 //si c'est pas char, alors soit c'est short, soit c'est pas short (donc int) :
 : (a == "short") ? short : int)
 //...et les trois qui restent, exactement pareil :
 : ((a == "long") ? long : (a == "float") ? float : double)
 //on check le premier type, et si c'est pas lui, on teste les deux autres.
Commentaire #88216 écrit par Alfred456654 le 10/04/2013 à 14h13 | 👍🏽 👎🏽
Mais heu... switch / case, toussa... c'est pas plus lisible ?

Par contre, comme ça fait longtemps que je n'ai pas touché du C, j'ai un peu du mal à comprendre la partie
TYPE(a) = ...
Il assigne un type de variable (int, char, etc.) au ... résultat de TYPE(a) ???
A l'aide quelqu'un ? Je suis complètement rouillé sur le C je crois... explications nécessaires... s'il vous plait ?
Commentaire #88223 écrit par Youplà le 10/04/2013 à 14h26 | 👍🏽 👎🏽
Voici une explication illustrée avec les types renommés :
http://img856.imageshack.us/img856/5396/20130410143106presentat.png
1 - char
2 - short
3 - int
4 - long
5 - float
6 - double
Commentaire #88225 écrit par Alfred456654 le 10/04/2013 à 14h33 | 👍🏽 👎🏽
Oui, c'est bien ça, mais TYPE(a) n'est pas une fonction, c'est du préprocesseur, donc ça "remplace textuellement" des choses dans le code avant la compilation, si ma mémoire est bonne.
Commentaire #88226 écrit par Alfred456654 le 10/04/2013 à 14h34 | 👍🏽 👎🏽
En fait, ça permet de créer des variables de ces types à partir de leur nom représenté dans un (char *).
à la précompilation, TYPE("float") sera remplacé par float, c'est pratique.
Commentaire #88227 écrit par Alfred456654 le 10/04/2013 à 14h37 | 👍🏽 👎🏽
Aaaah oui, ça y'est, y'a des vieux trucs qui commencent à se réveiller dans ma tête... Ok, je comprends mieux le contenu de ce PEBKAC maintenant.

Merci ! :)
Commentaire #88228 écrit par Youplà le 10/04/2013 à 14h40 | 👍🏽 👎🏽
Ben là tu m'as largué trééééés loin
Commentaire #88232 écrit par FunnyD le 10/04/2013 à 14h48 | 👍🏽 👎🏽
Il faut avoir fait un peu de C pour comprendre.
En gros, quand tu lances la compilation :
1 - les directives préprocesseur s'occupent de gérer les imports de librairies et exécutent les directives, comme celle citée dans ce PEBKAC
2 - chaque fichier est compilé
3 - les liens entre les fichiers sont faits (je ne suis pas à 100% sûr de ce que j'avance mais je crois pas être trop loin de la vérité).

La ligne incriminée ici indique que partout où il est écrit TYPE(<bidule>) dans le code, ça va être remplacé par le truc immonde à droite, avant que tout ne soit compilé.
Donc par exemple, si dans son code il a écrit TYPE("int") a = 5;, ce sera remplacé par int a = 5; au moment de la compilation.
Commentaire #88234 écrit par Alfred456654 le 10/04/2013 à 14h53 | 👍🏽 👎🏽
Ça montre surtout un absence totale de compréhension du C...

Même en rajoutant le define qui semble manquer et en enlevant le = probablement pas voulu, l'expansion des define ça n'exécute pas le code d'une part, et comparer des chaînes de caractères avec == ne donne pas le résultat escompté d'autre part.

OG.
Commentaire #88242 écrit par Olivier Galibert le 10/04/2013 à 15h36 | 👍🏽 👎🏽
Je ne me rappelle plus si les switch/case sont utilisable en C pour les chaines de caractères.
Commentaire #88245 écrit par Raizarachi le 10/04/2013 à 15h50 | 👍🏽 👎🏽
Techniquement, comparer des chaînes en C de cette façon fonctionnera, parce qu'on compare les pointeurs de chaîne de caractères, et que le compilateur, s'il est malin, réservera un seul espace mémoire pour "chaine" à la ligne 28 et "chaine" à la ligne 63842.

Mais on est bien d'accord que c'est complètement absurde...
Commentaire #88260 écrit par Lynix le 10/04/2013 à 17h35 | 👍🏽 👎🏽
si tu veux faire tout sur une ligne tu les imbrique proprement, pas comme un boucher russe (et j'ai rien contre nos amis russe).
voila une version un peu moins sale déjà :
# TYPE(a) = (a == "char")? char:((a == "short")? short:((a == "long")? long:((a == "float")? float:((a == "int")? int:double))))

tu a moins de code inutile, et ça tien en effet sur une ligne (ça me rappelle les formules de mes tableurs Calc XD)
Commentaire #88269 écrit par blag le 10/04/2013 à 18h38 | 👍🏽 👎🏽
Le = en trop, ça doit être une faute à moi, ça.
Commentaire #88273 écrit par Geist le 10/04/2013 à 18h56 | 👍🏽 👎🏽
Ooooh, le solde de votes est positif ! J'avais oublié à quoi ça ressemblait.

J'aurais du lui demander pourquoi il n'avait pas tout bonnement créé six fonctions différentes. Sans doute parce que ce garçon était obsédé par la légèreté du code. S'il était patron, je suppose qu'il paierait ses codeurs inversement proportionnellement au nombre de lignes de code (commentaires compris, parce qu'il faut bien les échapper).

La programmation a ceci en commun avec tout le reste que l'extrémisme, c'est mal.

Edit : aurait du ? aurait dû ? Doute atroce. GN, à l'aide.
Commentaire #88275 écrit par Geist le 10/04/2013 à 19h00 | 👍🏽 👎🏽
"aurait dû", avec "dû", participe passé du verbe devoir :)
Commentaire #88279 écrit par Pas GN mais presque le 10/04/2013 à 19h49 | 👍🏽 👎🏽
Je ne vois pas comment ça peut retourner quoi que ce soit d'utile. Ni quoi que ce soit tout court. Ni même compiler. Pour autant que je sache, on ne peut pas retourner un type. Ça ne veut rien dire on ; peut renvoyer 42 (qui sera a priori de type int), mais on ne peut pas renvoyer int.

EDIT : On pourrait a priori faire ce genre de chose en utilisant uniquement le préprocesseur, mais ici il utilise aussi des ternaires... Il compilait ce code ?
Commentaire #88286 écrit par danarmk le 10/04/2013 à 20h31 | 👍🏽 👎🏽
Ceci ne pourra jamais compiler. Le préprocesseur ne peut que faire des conditions sur des entiers.
Et il n'est pas possible de retourner un type : Cela n'a pas de sens...
Bref c'est horrible... Sinon en C++ il y a les templates :-)
Commentaire #88293 écrit par benjarobin le 10/04/2013 à 22h12 | 👍🏽 👎🏽
>> Sinon en C++ il y a les templates :-)

Et en C les pointeurs void :

Une liste en C qui date de mes cours au siècle dernier :

typedef struct _list list;
struct _list
{
void *value;
list *next;
list *prev;
}
Commentaire #88308 écrit par MilkEnd le 11/04/2013 à 10h29 | 👍🏽 👎🏽
Vous êtes tous une belle brochette de PEBKACs, mettre des pouces rouges aux deux seuls commentaires (ceux de Olivier G et danarmk) qui expriment simplement le problème:

ça ne peut pas marcher, car les types en C sont statiques (ils ne sont connus qu'a la compilation) et il essaie de les faire dépendre d'un test dont le résultat ne sera connu qu'a l'exécution; et, il utilise les types comme des expressions, ce qu'ils ne sont pas.
Commentaire #88309 écrit par b0fh le 11/04/2013 à 10h32 | 👍🏽 👎🏽
Oui, mais c'est déconseillé : ce sont les pointeurs qui sont comparés, donc deux chaînes identiques mais stockées à deux endroits différents en mémoire seront considérées différentes.
Commentaire #93164 écrit par Niouf le 19/05/2013 à 20h02 | 👍🏽 👎🏽
Si mon C est pas trop rouillé, en faisa
TYPE(a) = (a == "char" || a == "short" || a == "int") ? (( a == "char") ? char : (a == "short") ? short : int) : ((a == "long") ? long : (a == "float") ? float : double)
Commentaire #128532 écrit par Musaran le 05/02/2014 à 15h28 | 👍🏽 👎🏽
Si mon C est pas trop rouillé, en faisant abstraction du 1er = de trop, ce code remplace :
TYPE("char") par char
TYPE("short") par short
TYPE("int") par int
TYPE("float") par float
TYPE("double") par double

En gros c'est quasiment une opération nulle, car il pourrait directement écrire char, short, int etc.

Tout ça en dépendant d'un détail d'implémentation courant mais indéfini par le standard, et en supposant qu'il n'y ait pas d'autres types utilisés.
Commentaire #128533 écrit par Musaran le 05/02/2014 à 15h33 | 👍🏽 👎🏽
J'ai oublié
TYPE("long") par long

...ce qui ne change pas grand-chose.

D'ailleurs, cette façon d'utiliser des chaines de caractères au lieu de types appropriés s'appelle "stringly typed programming".
(jeu de mot anglais sur "strongly typed programming")
Commentaire #128534 écrit par Musaran le 05/02/2014 à 15h44 | 👍🏽 👎🏽