OVH Cloud OVH Cloud

Position sous-chaine

133 réponses
Avatar
Francois Cartegnie
Hello,

Je cherche un moyen de connaitre la position d'une occurence dans une chaine


J'ai essayé :
temp = strstr(bufferspace, "truc");
taille = temp-bufferspace;
Ne fonctionne pas car temp peut prendre la valeur NULL et donc le
compilateur refuse.

Etant dans l'espace noyau, je n'ai accès qu'a des fonctions sortant un
pointeur, et non la position.

Cordialement,

10 réponses

Avatar
Patrick Lamaizière
Gabriel Dos Reis écrivait :

Attachment decoded: text-plain-2
Attachment decoded: text-plain-3


Pas de multi-part s'il vous plait, merci.

Avatar
Antoine Leca
[contexte]
unsigned char *temp;
char * bufferspace;

taille = temp - bufferspace;
: invalid operands to binary -

Emmanuel Delahaye écrivit:
Je n'ai pas dit qu'ils étaient équivallent ni compatibles, mais

- il s'agit d'une différence de pointeurs et non pas des types de
base.
- de ce que j'en ai lu, la norme n'impose pas de diagnostic bloquant
si les types pointés sont différents.


6.5.6 Additive operators

Constraints

[#3] For subtraction, one of the following shall hold:

-- both operands are pointers to qualified or unqualified
versions of compatible object types; [or]


Et si pas compatible... pan pan !

Antoine

Avatar
Antoine Leca
Vincent Lefevre écrivit:
Dans l'article ,
Emmanuel Delahaye écrit:

Je ne vois pas écrit qu'il faille un diagnostic et arréter la
compilation si un opérande est signé et l'autre non. Mais toi qui a
une meilleure vue que moi, tu va me dire où c'est écrit.


En tout cas, c'est au moins du comportement indéfini.


Non non, cela demande un diagnostic, il y a violation de contrainte.
Cela étant, violation de contrainte ne signifie pas erreur (en C),
le compilateur peut accepter de générer le code. Il lui est juste
requis de signaler que ce n'est pas bien^H^H^H^Hportable.


Antoine


Avatar
Antoine Leca
Laurent Deniau écrivit:
Je ne vois pas écrit qu'il faille un diagnostic et arréter la
compilation si un opérande est signé et l'autre non. Mais toi qui a
une meilleure vue que moi, tu va me dire où c'est écrit.


parce qu'un char n'est ni signe ni non signe.


Oui.

la norme dit clairement (derniere ligne) que char est un cas a part.


Bof. Dernière ligne de quoi, d'ailleurs ?
Rappel : les notes de bas de page ne sont pas normatives.

en particulier on a la
garantie que sizeof(signed char) == sizeof(unsigned char)


Oui.

mais pas sizeof(char) == sizeof(signed char)


Ah bon ? Où cela ? Jamais rien vu de pareil.
Relis donc 6.2.5p5...

d'ou le probleme dans la soustraction...


Comprend plus.
Le diagnostic serait le même (en fait, serait encore plus
justifié) si on avait (unsigned char*)p - (signed char*)q.

En l'occurence, du fait des contraintes spécifiques sur
les tableaux de caractères (en C99, 6.2.6, 6.2.5p15),
on sait que cela "doit" fonctionner. Mais ce n'est pas "légal".


mettre un signed devant le premier char devrait resoudre le probleme.


Non.


Par contre, as-tu bien compris le sens du message émis par gcc? Ne
serait-ce pas un bug par hasard? Tout est possible...


non ce n'est pas un bug. le code est un UB.


Non. Le comportement est parfaitement défini (6.5.6p9).
C'est "seulement" illégal, ce qui est très différent du
comportement indéfini (bon, OK, je suppose ici que les
deux pointeurs "pointent" dans le même tableau).


Antoine


Avatar
Antoine Leca
Gabriel Dos Reis écrivit:
notamment le comité C.


Partisan.


Antoine

Avatar
Antoine Leca
Erwan David writes:

si je fais typedef int mon_type;
alors int et mon_type sont interchangeables. typedef défini un
alias. J'aimerais souvent pouvoir définir un type en disant c'est
représenté comme int mais ce n'est pas interchangeable avec un int.



enum {_min=INT_MIN, _max=INT_MAX};

Ça va bien le faire en C++, en C je pense que cela va être un peu
court ; mais avec les pointeurs les compilos en -Wmax devrait te
génèrer les tombereaux d'injures que tu désires, non ?


Antoine


Avatar
Antoine Leca
Laurent Deniau écrivit:
6.2.5-15

The three types char, signed char, and unsigned char are collectively
called the character types. The implementation shall define char to
have the same range, representation, and behavior as either signed
char or unsigned char.32)

32) CHAR_MIN, defined in <limits.h>, will have one of the values 0 or
SCHAR_MIN, and this can be used to distinguish the two options.
Irrespective of the choice made, char is a separate type from the
other two and is not compatible with either.

Pour moi, les deux dernieres phases des deux paragraphes sont
contradictoires et:


Tu peux laisser tomber la note de fin de page, elle n'a pas plus de
valeur que mes messages (ou les tiens).

1- meme range, meme representation(!), meme comportement
2- MAIS incompatible.

dans la pratique, je ne vois pas comment c'est possible a moins de le
decreter (sans fondement) histoire de faire ch... Pour moi char doit
etre compatible avec un des deux types signed char ou unsigned char
mais c'est implementation defined donc pas portable.


Je pense que tu n'as pas compris à quoi sert d'avoir _trois_ types.

Il y a trois types, parce qu'il y a trois besoins (stocker un caractère,
stocker un entier signé de petite magnitude, stocker un entier
non signé de petite magnitude et assurer ainsi des calculs vérifiables).
Si tu regardes d'autres langages de programmation, par exemple
(au hasard !) Pascal ou Ada, tu vas voir qu'il y a effectivement trois
types (quelque chose comme Char, Very_Short_Integer,
Very_Short_Unsigned_Integer/Byte).

En C, pour des raisons historiques, les caractères sont encodés comme
des entiers. Cela facilite certaines opérations. Mais, toujours sur un
plan historique, il y a eu (et il y a toujours) une divergence fondamentale
entre les implémentations où il est plus facile d'utiliser des octets signés
(étendus en int pour faire les opérations) que des non signés, d'un côté
(genre, le PDP-11 originel, ou certaines machines Risc), et de l'autre côté
le code EBCDIC où '0' nécessite impérativement le huitième bit...
De ce fait, depuis le début des 80's, on se trimbale une altenative sur
le signe de char.

Pour être portable, il est indispensable, bien sûr, de ne faire aucune
hypothèse sur cette alternative. La méthode la plus sûre, pour se faire,
est de bien identifier les trois besoins différents, et d'empêcher les
mélanges. Et c'est pour cela que les trois types sont incompatibles.

L'alternative, proposée au comité C par Microsoft (il y a 15 ans de cela),
consistait à dire "char est un alias de soit l'un, soit l'autre"; autrement
dit,
il n'y a que deux types (c'est ce qui implementé dans le C1 de VC++).
Il me paraît clair (mais on peut en discuter) que le choix du comité C est
meilleur du point de vue de la portabilité, même si pour un utilisateur
particulier (lié à un seule plateforme, donc non gêné par l'alternative),
cela
peut paraître ch...


Antoine

Avatar
Gabriel Dos Reis
"Antoine Leca" writes:

[...]

| > dans la pratique, je ne vois pas comment c'est possible a moins de le
| > decreter (sans fondement) histoire de faire ch... Pour moi char doit
| > etre compatible avec un des deux types signed char ou unsigned char
| > mais c'est implementation defined donc pas portable.
|
| Je pense que tu n'as pas compris à quoi sert d'avoir _trois_ types.
|
| Il y a trois types, parce qu'il y a trois besoins (stocker un caractère,
| stocker un entier signé de petite magnitude, stocker un entier
| non signé de petite magnitude et assurer ainsi des calculs vérifiables).

et tripafouiller de la mémoire brute. C classic, utilisait char. Le
comité a introduit void* à la place, mais n'a pas étandu les règles
d'arithmétique de pointeur. Bien sûr, on peur caster void* and char*
et faire l'arithmétique, mais il aurait été plus simple d'avoir
l'arithmétique directement une fois que le pas a été franchis.

-- Gaby
Avatar
Laurent Deniau
Gabriel Dos Reis wrote:
"Antoine Leca" writes:

[...]

| > dans la pratique, je ne vois pas comment c'est possible a moins de le
| > decreter (sans fondement) histoire de faire ch... Pour moi char doit
| > etre compatible avec un des deux types signed char ou unsigned char
| > mais c'est implementation defined donc pas portable.
|
| Je pense que tu n'as pas compris à quoi sert d'avoir _trois_ types.
|
| Il y a trois types, parce qu'il y a trois besoins (stocker un caractère,
| stocker un entier signé de petite magnitude, stocker un entier
| non signé de petite magnitude et assurer ainsi des calculs vérifiables).

et tripafouiller de la mémoire brute. C classic, utilisait char. Le
comité a introduit void* à la place, mais n'a pas étandu les règles
d'arithmétique de pointeur. Bien sûr, on peur caster void* and char*
et faire l'arithmétique, mais il aurait été plus simple d'avoir
l'arithmétique directement une fois que le pas a été franchis.


Par forcement (en tout cas c'est pas mon avis). On peut utiliser void* pour
faire de l'ADT, et authoriser une arithmetique dessus peut-etre dangereux pour
qui manipulerait par inadvertance des pointeurs de ce type.

Typiquement mon ADT en C ressemble a ca:

#define D_ADT struct { void const * const _; } *

typedef D_ADT array;
typedef D_ADT list;

(le define est dans un header a part) independament des const, ca m'embeterait
que l'utilisateur puisse changer la valeur de _ sans le faire expres ne sachant
pas vers quoi il pointe.

je pense qu'il existe beaucoup de vieux codes moins "proteger" (pas de struct,
pas de const) qui pourrait avoir ce type de probleme si on autorisait
l'arithmetique sur void*.

a+, ld.

--
[ Laurent Deniau -- Scientific Computing & Data Analysis ]
[ CERN -- European Center for Nuclear Research ]
[ - http://cern.ch/Laurent.Deniau ]
[ -- One becomes old when dreams become regrets -- ]

Avatar
Vincent Lefevre
Dans l'article <bh7pqt$hq3$,
Antoine Leca écrit:

Vincent Lefevre écrivit:
Dans l'article ,
Emmanuel Delahaye écrit:

Je ne vois pas écrit qu'il faille un diagnostic et arréter la
compilation si un opérande est signé et l'autre non. Mais toi qui a
une meilleure vue que moi, tu va me dire où c'est écrit.


En tout cas, c'est au moins du comportement indéfini.


Non non, cela demande un diagnostic, il y a violation de contrainte.
Cela étant, violation de contrainte ne signifie pas erreur (en C),
le compilateur peut accepter de générer le code. Il lui est juste
requis de signaler que ce n'est pas bien^H^H^H^Hportable.


Oui, mais une violation de contrainte, c'est un cas particulier
de comportement indéfini (avec des choses en plus), non? D'où mon
"au moins". Du code peut être généré, mais si l'implémentation ne
spécifie rien, il peut se passer n'importe quoi.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/> - 100%
validated (X)HTML - Acorn Risc PC, Yellow Pig 17, Championnat International
des Jeux Mathématiques et Logiques, TETRHEX, etc.
Work: CR INRIA - computer arithmetic / SPACES project at LORIA