Partage
  • Partager sur Facebook
  • Partager sur Twitter

Combinaison a 3 chiffres differents

Peu de piste

Sujet résolu
Anonyme
27 août 2012 à 23:10:07

Citation : Gwenn

Une rectification s'impose de mon côté : le diff entre les deux binaires était foiré, il n'y a aucune différence (à ma grande surprise, d'ailleurs) entre les deux binaires autre que les noms des fichiers.

Dans un cas réel avec une variable, je pense que le code généré serait différent, je maintiens ce que je pense sur la sémantique, mais effectivement sur un code basique le code généré en -O2 est strictement identique. Désolé !


Il n'y aucune différence effectivement, comme je l'ai dis, puisque nécessairement le compilateur ne saura pas optimiser.
Par contre, il y a des différences si tu fais ceci :
void foo() {
    while(i < 100000) {
        while(j < 100000) {
            j++;
        }
    i++;
    }
}


void bar() {
    for(int i = 0; i < 100000; i++) {
        for(int j = 0; j < 100000; j++) {
        }
    }
}


Dans le second cas, le compilateur ne passera même pas dans les boucles, alors qu'il passera dans le premier cas.
Tu peux également rajouter des calculs qui n'ont pas d'influence sur le reste, gcc l'optimise également (à ma grande surprise, c'était plutôt chiant pour des benchmarks. J'ai découvert ça il y a quelques jours) :
void bar() {
    int a[100000];
    int b[100000];

    for(int i = 0; i < 100000; i++)
       a[i] = i;

    for(int i = 0; i < 100000; i++)
       b[i] = i;
    for(int i = 0; i < 100000; i++) {
        for(int j = 0; j < 100000; j++) {
             a[i] += j*b[i];
        }
    }
}


C'était grosso-modo le code que je voulais utiliser pour avoir un tant CPU conséquent. Tellement bien optimisé que malgré la taille et malgré le nombre de boucle imbriqué, j'avais toujours un temps de quelques millisecondes. Il ne passaient effectivement pas dedans parce qu'aucune des variables n'était utilisé ailleurs que localement et n'avait aucune incidence sur des variables locales dont la valeur étaient utilisées ailleurs.
  • Partager sur Facebook
  • Partager sur Twitter
28 août 2012 à 0:01:48

Citation : Hod

Dans le second cas, le compilateur ne passera même pas dans les boucles, alors qu'il passera dans le premier cas.


Ton code ne compile pas, donc je suppose que tu n'as pas testé. Il aurait peut-être fallu parce que chez moi, on ne passe dans les boucles dans aucun cas.

Génération des fichiers asm a.s et b.s et comparaison (ils sont identiques à part pour le nom du fichier .c d'origine) :
[dentuk@myhost tmp]$ cat a.c; gcc a.c -O2 -S
#include <stdio.h>

void foo() {
  int i, j;
  i = 0;
  while(i < 100000) {
    j = 0;
    while(j < 100000) {
      j++;
    }
    i++;
  }
}

int main(void) {
  foo();
  return 0;
}
[dentuk@myhost tmp]$ cat b.c; gcc b.c -O2 -S
#include <stdio.h>

void foo() {
  int i, j;
  for(i = 0; i < 100000; i++) {
    for(j = 0; j < 100000; j++) {
    }
  }
}

int main(void) {
  foo();
  return 0;
}
[dentuk@myhost tmp]$ diff a.s b.s
1c1
<         .file        "a.c"
---
>         .file        "b.c"
[dentuk@myhost tmp]$ gcc --version
gcc (GCC) 4.7.0 20120505 (prerelease)
Copyright © 2012 Free Software Foundation, Inc.
Ce logiciel est libre; voir les sources pour les conditions de copie.  Il n'y a PAS
GARANTIE; ni implicite pour le MARCHANDAGE ou pour un BUT PARTICULIER.

Code généré pour la fonction foo :
        .cfi_startproc
        rep
        ret
        .cfi_endproc
  • Partager sur Facebook
  • Partager sur Twitter
28 août 2012 à 2:10:59

Citation : ledenomejojo

Et quand je dis qu'on a pas le droit d'utiliser de lib, en gros je veux dire qu'aucun fichier ne doit être inclus dans les *.c sauf nos propre fichier. (stdlib.h et stdio.h par exemple ne doivent pas être inclus) Enfin je crois...


Tiens, à ce propos, j'ai dû révoquer plusieurs fois un contributeur insistant qui retirait cette inclusion d'un exemple de Wikipédia. Et il confondait bibliothèque et inclusion. Enfin bref, s'il était possible de dissiper les inexactitudes à ce sujet, ce serait cool. ^^
En effet, à moins d'écrire vraiment salement, il faut tinclure <unistd.h> qui contient le prototype de la fonction write :
ssize_t write(int fildes, const void *buf, size_t nbyte);

Quant à write, ça fait partie des appels système classiques de Unix. Typiquement, c'est implémenté en passant par la libc, qui contient une fonction write appelable en C, et qui elle-même n'est qu'un stub qui fait l'appel système proprement dit. Enfin, pour le détail exact, voir votre système ( http://fxr.watson.org/fxr/source/kern/syscalls.master , http://syscalls.kernelgrok.com/ , etc.)
  • Partager sur Facebook
  • Partager sur Twitter
28 août 2012 à 3:15:21

Citation : ledenomejojo

Et quand je dis qu'on a pas le droit d'utiliser de lib, en gros je veux dire qu'aucun fichier ne doit être inclus dans les *.c sauf nos propre fichier. (stdlib.h et stdio.h par exemple ne doivent pas être inclus) Enfin je crois...

Ah j'avais pas lu ça, mais en tout cas si à l'école tu as le droit d'inclure tous les .h du monde, tant que tu n'utilises pas les fonctions temporairement interdite.
  • Partager sur Facebook
  • Partager sur Twitter
28 août 2012 à 9:03:12

Ah d'accord, je ne savais pas, je savais juste qu'on avait pas le droit d'utiliser des fonction comme printf ou des boucles comme for pendant la piscine. Merci pour l'info :)
PS : Désolé si j'ai réveiller un vieux post qui a mal tourner, ce n'était pas mon intention. Mais a ce que je vois, ça s'arrange :)
  • Partager sur Facebook
  • Partager sur Twitter
DNTUI
28 août 2012 à 23:44:35

Ce debat n'a vraiment rien d'interessant ... :/

Oui certaines parties (beaucoup) de la norme d'epitech appliquee sur le C est stupide et contre productif (comme l'interdiction de for, switch, break entre autre bien casse couille) mais certaines parties on un interet ( comme les 25 lignes de fonctions ) je n'ai pas d'autre exemple en tete la n'etant plus confronter a cette norme depuis un certains temps,

Dans le cas du for et while, j'ai personnellement toujours preferer un for ( non pas pour une meilleur performance ou d'optimisation) mais parce qu'elle permet de reduire le code et de le rendre plus lisible en declarant/initialisant directement les variables necessaires a cette boucle.
  • Partager sur Facebook
  • Partager sur Twitter
29 août 2012 à 0:45:52

Je crois qu'en fait, on se fout du contenu de la norme Epitech, tant qu'elle ne sort pas d'Epitech. J'ai vu un Epitech au boulot, il ne code pas avec ces règles, donc, en généralisant, pour ceux qui sont sortis de l'école, c'est bon. Pour ceux qui y sont, je pense qu'on attend d'eux de savoir réécrire un code selon une autre norme, donc ils n'ont pas à nous emmerder avec sur un forum publique. Notez que ça ne concerne pas que la norme de la piscine Epitech. Celui qui vient ici en se plaignant que les codes ne respectent pas les règles MISRA, je me ferai un plaisir de leur expliquer pourquoi elles n'ont pas lieu d'être ici.

Et, concernant les compilo, ceux qui ont subit autant de dev que GCC gèrent les dépendances entre instructions, les accès mémoires, etc... Du coup, il vaut mieux coder en pensant à la sémentique qu'à un code pour un humain plutôt qu'à l'efficacité du code, ce second point n'étant humainement estimable que pour des compilations naïves (je parle bien ici des optimisations genre "réutiliser une variable plutôt qu'en déclarer une deuxième, faire un for ou un while... La complexité algorithmique, elle, doit rester en tête des préoccupations du développeur, en la nuance par l'importance du segment de code dans le programme).
  • Partager sur Facebook
  • Partager sur Twitter
64kB de mémoire, c'est tout ce dont j'ai besoin
29 août 2012 à 9:04:13

Nathalya >> Oui on s'en fou clairement mais tout se debat a ete lancer a cause justement de cette norme et de la pseudo interdiction de for (norme qui par ailleurs n'est valable que pendant la premiere annee [moitie])

Citation : ledenomejojo

Ah d'accord, je ne savais pas, je savais juste qu'on avait pas le droit d'utiliser des fonction comme printf ou des boucles comme for pendant la piscine. Merci pour l'info :)



interdit tant que tu ne les a pas recoder ( juste apres la piscine ) :p
  • Partager sur Facebook
  • Partager sur Twitter
29 août 2012 à 9:25:40

Citation : Nathalya

Je crois qu'en fait, on se fout du contenu de la norme Epitech, tant qu'elle ne sort pas d'Epitech.


Oui. Plus généralement, quel que soit l'endroit où l'on soumet du code, il y a des conventions, et si on ne les suit pas, on se fait rabrouer. Sur un forum Internet, les conventions sont assez souples, mais tout de même pas suffisamment souples pour être compatibles avec les conventions destinées aux primo-débutants d'Epitech.
À chaque public sa convention, et celui qui ne s'y plie pas n'a pas à s'étonner de se faire rabrouer, que ce soit ici où dans son école.
  • Partager sur Facebook
  • Partager sur Twitter
29 août 2012 à 12:38:56

@Accro -> Ah d'accord, il faut les recoder x)
Bah je vais m'y mettre maintenant alors x)
  • Partager sur Facebook
  • Partager sur Twitter
DNTUI
29 août 2012 à 13:03:42

ledenomejojo, tu peux deja recoder string.h ^^

my_strlen
my_str(n)cpy
my_str(n)cat
my_str(n)cmp
my_mem(move|cpy|set)
etc.

Citation : Nathalya

donc ils n'ont pas à nous emmerder avec sur un forum publique

Je suis d'accord (pour souligner le fait que ce n'est pas moi qui est parle du for)
  • Partager sur Facebook
  • Partager sur Twitter
29 août 2012 à 13:07:07

@Mr21 -> Je prend note, je le fais demain :)
Merci.

Je commencer ce matin dans le train my_aff_combn(int n), me manque plus que 3-4 ligne et c'est fini.

PS : C'est quoi le (n) ? dans my_str(n)cpy par exemple ?
  • Partager sur Facebook
  • Partager sur Twitter
DNTUI
29 août 2012 à 13:11:36

c'est juste qu'il y a strcat et strncat par exemple le second prenant une taille en +.
  • Partager sur Facebook
  • Partager sur Twitter
29 août 2012 à 13:16:56

Ce sont les soeurs, les cousines des fonctions "simples", par exemple, strncpy est pratiquement identique à strcpy, sauf que strncpy ne copie qu'un certain nombre de caractères. Au lieu de copier toute la chaine source dans la chaine de destination (comportement de strcpy), on peut demander à strncpy de ne copier que <math>\(n\)</math> caractères.

char * strcpy(char * dest, const char * src);
char * strncpy(char * dest, const char * src, size_t n);
  • Partager sur Facebook
  • Partager sur Twitter
29 août 2012 à 15:25:50

D'accord, merci beaucoup :)
  • Partager sur Facebook
  • Partager sur Twitter
DNTUI
29 août 2012 à 15:49:56

Citation : paraze

par exemple, strncpy est pratiquement identique à strcpy, sauf que strncpy ne copie qu'un certain nombre de caractères. Au lieu de copier toute la chaine source dans la chaine de destination (comportement de strcpy), on peut demander à strncpy de ne copier que <math>\(n\)</math> caractères.


En fait la fonction strncpy est très piègeuse et sémantiquement différente de strcpy. Son usage est généralement déconseillé.
La fonction strncpy est destinée à copier une chaine dans un champ de taille fixe. C'est pour cela qu'elle rempli la fin du champ de '\0' si la chaine est plus courte, et qu'elle ne met pas de '\0' terminal si le champ est plus petit que la chaine. Le résultat de strncpy n'est donc pas forcément une chaine!
  • Partager sur Facebook
  • Partager sur Twitter
29 août 2012 à 15:59:30

Citation

C'est pour cela qu'elle rempli la fin du champ de '\0'

d'un '\0', elle ne va pas faire une boucle jusqu'au reste quoi. (ah non jai du mal comprendre desole, j'ai inverse les variables...)

Pour inserer une chaine dans une autre par exemple: c'est memmove + strncpy pour ne pas mettre justement le '\0'.
  • Partager sur Facebook
  • Partager sur Twitter
29 août 2012 à 16:19:12

Citation : Mr21

Pour inserer une chaine dans une autre par exemple: c'est memmove + strncpy pour ne pas mettre justement le '\0'.


Pour insérer une chaine dans une autre, c'est memmove et memcpy.
Bien sûr, stncpy et memcpy font la chose si la taille qu'on leur passe est plus petite que la longueur de la chaine à copier. Mais strncpy implémente toute une logique supplémentaire, qui ne sert à rien dans une insertion, et qui ralentit inutilement l'exécution.
  • Partager sur Facebook
  • Partager sur Twitter
29 août 2012 à 16:27:46

Je savais pas merci :) ca expliquerai peut etre pourquoi strcat est plus rapide que strcpy (sans O2 etc.).

C'est etrange car ca semble inverse:

strncpy fait pour autre chose qu'une chaine.
Et memcpy utile justement pour ca.

Les prototypes indiquent pourtant l'inverse non?
  • Partager sur Facebook
  • Partager sur Twitter
29 août 2012 à 17:22:36

Citation : Mr21

C'est etrange car ca semble inverse:


Oui c'est une étrangeté du langage. En fait, le nom de strncpy a été mal choisi.

Citation : C99 Rationale §7.21.2.4 The strncpy function

strncpy was initially introduced into the C library to deal with fixed-length name fields in structures such as directory entries. Such fields are not used in the same way as strings: the trailing null is unnecessary for a maximum-length field, and setting trailing bytes for shorter 5 names to null assures efficient field-wise comparisons. strncpy is not by origin a “bounded strcpy,” and the Committee preferred to recognize existing practice rather than alter the function to better suit it to such use.



Voir aussi https://lwn.net/Articles/507376/ .
  • Partager sur Facebook
  • Partager sur Twitter
15 avril 2023 à 0:49:56

Pour l'exercice, il y a un moyen plus simple de le résoudre en utilisant les modulos

-
Edité par valerianDorcy 15 avril 2023 à 0:52:56

  • Partager sur Facebook
  • Partager sur Twitter
15 avril 2023 à 1:02:30

@valerianDorcy:
Pourquoi avoir effacé toncode? J'ai eu le temps de le voir ...
Tu as déterré un vieux sujet de 2008 prolongé jusqu'en 2012.
Je l'aurais sans doute fait avec un compteur kilométriqque.

Si ça t'intéresse, crée un nouveau sujet.

-
Edité par PierrotLeFou 15 avril 2023 à 1:06:25

  • Partager sur Facebook
  • Partager sur Twitter

Le Tout est souvent plus grand que la somme de ses parties.

15 avril 2023 à 3:33:17

@valerianDorcy Bonsoir, merci de ne pas déterrer d'ancien sujet résolu.

Déterrage

Citation des règles générales du forum :

Avant de poster un message, vérifiez la date du sujet dans lequel vous comptiez intervenir.

Si le dernier message sur le sujet date de plus de deux mois, mieux vaut ne pas répondre.
En effet, le déterrage d'un sujet nuit au bon fonctionnement du forum, et l'informatique pouvant grandement changer en quelques mois il n'est donc que rarement pertinent de déterrer un vieux sujet.

Au lieu de déterrer un sujet il est préférable :

  • soit de contacter directement le membre voulu par messagerie privée en cliquant sur son pseudonyme pour accéder à sa page profil, puis sur le lien "Ecrire un message"
  • soit de créer un nouveau sujet décrivant votre propre contexte
  • ne pas répondre à un déterrage et le signaler à la modération

Je ferme ce sujet. En cas de désaccord, me contacter par MP.

  • Partager sur Facebook
  • Partager sur Twitter