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
Vincent Lefevre
Dans l'article <bh88lc$f7l$,
Antoine Leca écrit:

Vincent Lefevre écrivit:
Dans l'article <bh7r8s$ka3$,
Antoine Leca écrit:

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".


Comment ça, "fonctionner"?


Si tu fais abstraction de la clause spécifique de 6.5.6
qui énonce la contrainte. On peut concevoir, pour le cas
particulier des pointeurs vers type caractère, une relaxe de
cette contrainte. Et alors, le reste « fonctionne ».


Il n'y a pas que la contrainte de 6.5.6. Dans 6.5.6#9, le
comportement n'est défini que dans ce cas:

[#9] When two pointers are subtracted, both shall point to
elements of the same array object, or one past the last
element of the array object;

L'implémentation peut très bien émettre
un diagnostic et renvoyer 0 pour toute opération du style
(unsigned char*)p - (signed char*)q.


Oui oui. Je ne me place plus dans le cadre de la norme,
l'essayais d'imaginer ce qui se passe si on enlève la
contrainte.


Il faudrait alors que la norme dise ce qui se passe dans le cas de
tableaux différents. Par exemple, lorsque les éléments ont la même
taille (et le même alignement).

Dans ce cas, tu ne "peux plus" renvoyer 0, il "faut" renvoyer la
valeur logique et naturelle, sur laquelle il n'y a pas ce me semble
d'ambiguité, même dans le cas des architectures tordues (il faut
bien voir que vu du comité, les cas explicites de comportement
indéfini sont en fait les cas où « cela ne passe pas » pour
certaines architectures).


Mais la norme ne parle pas de logique et de naturel.

--
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



Avatar
Vincent Lefevre
Dans l'article <bh896s$ggb$,
Antoine Leca écrit:

Mmmm. D'abord, pour les langages conçus aujourd'hui (et qui
ne cherchent pas la compatibilité avec C), char existe, mais il
est (potentiellement) plus grand qu'un byte; ce qui résoud le
problème.


Non, impossible: sizeof(char) == 1, et c'est 1 byte:

[#1] byte
addressable unit of data storage large enough to hold any
member of the basic character set of the execution
environment

Ce qui n'existe plus « si c'était à refaire », c'est l'affirmation
comme quoi l'unité de stockage élémentaire (le byte ou multiplet,
et en pratique l'octet) permette de stocker un caractère.


Oui.

--
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

Avatar
Antoine Leca
Laurent Deniau écrivit:
Abstract Data Type. Un objet dont l'utilisateur n'a absoluement rien
a savoir hormis les fonctions qui lui sont applicables (interface).


Ah. Quelque chose comme

struct adt;


C'est exactement ce que je veux. C'est pour palier au probleme des
alias.

typedef void* object;
typedef object array;
typedef object list;


typedef struct elem array[];
typedef struct list_elem list;

Si tu y tiens,

typedef struct elem object;

Mais cela n'apporte rien, àmha.

J'ai voulu avoir qqchose dont l'utilisateur ne peut rien faire sans
transtypage violent auquel cas il rompt le contrat.


Mmmmmmmmmmmmmmmmmmmm...

J'ai tendance à penser que la volonté de « programmer en C sans
transtypage » rentrait dans le même genre de catégorie que
« programmer sans aucun warning a -W4 -Za » ou « programmer
sans goto » (et si vous voulez une IHM Windows avec les trois en
même temps, je vous souhaite bien du plaisir ;-)).

Autrement dit, les transtypages sont un mal nécessaire en C.
Alors ayez pitié pour celui qui maintient le code derrière, et
laissez-lui en le moins possible; parce qu'il va devoir vérifier
un par un tous les transtypages en cas de pépin...


Peut-être; cela étant, si C était un langage « sûr », cela se
saurait...


Cela a ces avantages et ces inconvenients. Avec un peu de methode et
de discipline de programmation, il peut le devenir suffisamment pour
de gros projet sans devenir un casse tete pour autant.



Bien sûr. Cela étant, àmha il n'est pas nécessaire de rajouter
const dans ton type : cela invite au meutre, et j'ai du mal à
voir la valeur ajoutée.


Antoine


Avatar
Gabriel Dos Reis
"Antoine Leca" writes:

| Gabriel Dos Reis écrivit:
| > Antoine Leca writes:
| >> Cela étant, violation de contrainte ne signifie pas erreur (en C),
| >>
| > la règle est la même en C++. On émet un diagnostique et on fait ce
| > que tu veux après.
|
| En C++ tu as le droit de générer le code objet pour du code
| ill-behaved ?

1.4/8
A conforming implementation may have extensions (including
additional library functions), provided they do not alter the
behavior of any well-formed program. Implementations are required
to diagnose programs that use such extensions that are ill-formed
according to this International Standard. Having done so, how-ever,
they can compile and execute such programs.

| En tous cas, le texte de la norme (« programme mal formé ») incite à
| beaucoup plus de prudence que celui de C qui ne fait rien d'autre
| que mentionner l'obligation d'émettre un « diagnostic ».

C'est vrai -- j'ai d'ailleurs été surpris par la formulation C.

-- Gaby
Avatar
Gabriel Dos Reis
--=-=- Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit

"Antoine Leca" writes:

| Gabriel Dos Reis écrivit:
| > Ce qui m'intéresse en premier lieu c'est de pouvoir implémenter
| > quelque chose comme my_memcpy(void*, const void*, int).
|
| void *my_memcpy(void* a, const void* b, int c).{ return memcpy(a,b,c); }

--=-=- Content-Type: text/plain; charset=iso-8859-15
Content-Transfer-Encoding: quoted-printable


non, pas ças -- il est notoire que memcpy sur certaines
implémentations sont très lentes.

--=-=- Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit


| > comment imnplémenter my_qsort() en faisant de l'arithmétique sur
| > void* ?
|
| En appelant qsort :-D

pas acceptable non plus.

| Qui a dit que l'implémentation de la bibliothèque standard devait être
| strictement conforme, ou « jolie », ou même écrite en C ?

--=-=- Content-Type: text/plain; charset=iso-8859-15
Content-Transfer-Encoding: quoted-printable


Je n'ai pas dit que je voulais implémenter la bibliothèque standard C.

| C'est pas Java/C# ici, que diable !

Cela n'a rien à avoir.

-- Gaby

--=-=-=--
Avatar
Gabriel Dos Reis
--=-=- Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit

Laurent Deniau writes:

| Antoine Leca wrote:
| > Laurent Deniau écrivit:
| >
| >>Typiquement mon ADT en C ressemble a ca:
| > Heu, excusez la question du Neu-neu, ADT, que es aco?
|
| Abstract Data Type. Un objet dont l'utilisateur n'a absoluement rien a
| savoir hormis les fonctions qui lui sont applicables (interface).
|
| >>#define D_ADT struct { void const * const _; } *
| > Dangereux cela, tu définis un structure anonyme (différente)
| > à chaque invocation de la macro; c'est peut-être ce que tu
| > veux, mais d'autres pourrait facilement se méprendre...
|
| C'est exactement ce que je veux. C'est pour palier au probleme des alias.

--=-=- Content-Type: text/plain; charset=iso-8859-15
Content-Transfer-Encoding: quoted-printable


Comment ? À partir du moment où tu mets void* en début de ta
structure, tu dis au compilo que n'importe quel pointeur de données
peut aliaser ta structure. I.e. tu fais exactement el contraire de ce
que tu voudrais.

|
| typedef void* object;
| typedef object array;
| typedef object list;
|
| une list peut aller la ou un array est attendu, ce que je ne veux pas.

Mais ce que tu as proposé aupravant n'est pas une solution non plus !

-- Gaby

--=-=-=--
Avatar
Gabriel Dos Reis
Vincent Lefevre <vincent+ writes:

| Dans l'article ,
| Gabriel Dos Reis écrit:
|
| > mouais, mais alors le même argument s'applique pour la conversion
| > implicite void* -> T* pour n'importe quel T, type d'objet. Cette
| > conversion implicite est beaucoup plus pernicieuse que l'arithmétique.
|
| Pourquoi? Le programmeur n'est-il pas censé connaître son langage et
| programmer en conséquence?

Oui et alors ? Tu n'as jamais fait d'erreur ?

-- Gaby
Avatar
Laurent Deniau
Antoine Leca wrote:
Laurent Deniau écrivit:

Abstract Data Type. Un objet dont l'utilisateur n'a absoluement rien
a savoir hormis les fonctions qui lui sont applicables (interface).



Ah. Quelque chose comme

struct adt;


Non.

C'est exactement ce que je veux. C'est pour palier au probleme des
alias.

typedef void* object;
typedef object array;
typedef object list;



typedef struct elem array[];
typedef struct list_elem list;


Ce n'est pas du tout ce que je veux.

Si tu y tiens,

typedef struct elem object;

Mais cela n'apporte rien, àmha.


Si. Pour etre plus clair, voici un code qui montre le probleme:

#include <stddef.h>
#include <assert.h>

#define ADT struct { void *_; } *
typedef ADT list;
typedef ADT array;

/* pas de warnings avec ce cas
struct adt;
typedef struct adt *list;
typedef struct adt *array;
*/

void list_foo (list l) { assert(l); }
void array_foo(array a) { assert(a); }

int
main(void)
{
list l = NULL;
array a = NULL;

list_foo(l);
list_foo(a); /* warning */

array_foo(a);
array_foo(l); /* warning */

return 0;
}


gcc -Wall -W adt.c
adt.c: In function `main':
adt.c:24: warning: passing arg 1 of `list_foo' from incompatible pointer type
adt.c:27: warning: passing arg 1 of `array_foo' from incompatible pointer type

Bien sûr. Cela étant, àmha il n'est pas nécessaire de rajouter
const dans ton type : cela invite au meutre, et j'ai du mal à
voir la valeur ajoutée.


Comme je l'ai dit, les const dans ADT sont inutiles. Mais par coherence avec
d'autres objets du meme genre ou les const sont utiles je les mis aussi ici.
Certe, ils sont en trop pour cette discussion et j'aurais du les enlever comme
ci-dessus.

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
Laurent Deniau
Gabriel Dos Reis wrote:
Laurent Deniau writes:

| Antoine Leca wrote:
| > Laurent Deniau écrivit:
| >
| >>Typiquement mon ADT en C ressemble a ca:
| > Heu, excusez la question du Neu-neu, ADT, que es aco?
|
| Abstract Data Type. Un objet dont l'utilisateur n'a absoluement rien a
| savoir hormis les fonctions qui lui sont applicables (interface).
|
| >>#define D_ADT struct { void const * const _; } *
| > Dangereux cela, tu définis un structure anonyme (différente)
| > à chaque invocation de la macro; c'est peut-être ce que tu
| > veux, mais d'autres pourrait facilement se méprendre...
|
| C'est exactement ce que je veux. C'est pour palier au probleme des alias.


------------------------------------------------------------------------


Comment ? À partir du moment où tu mets void* en début de ta
structure, tu dis au compilo que n'importe quel pointeur de données
peut aliaser ta structure. I.e. tu fais exactement el contraire de ce
que tu voudrais.


Ce qui est dans la structure n'est pas important et j'aurais pu mettre n'importe
quoi d'autre. C'est le fait que ce soit une structure qui est important. Le *
final t'aurait-il echappe? array et list sont des pointeurs.

| typedef void* object;
| typedef object array;
| typedef object list;
|
| une list peut aller la ou un array est attendu, ce que je ne veux pas.

Mais ce que tu as proposé aupravant n'est pas une solution non plus !


Si, cf exemple dans l'autre post (celui qui precede celui-ci). Mais suis preneur
de meilleures idees qui n'utilise pas de define :-)

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
Antoine Leca
Laurent Deniau écrivit:
Antoine Leca wrote:
Laurent Deniau écrivit:

Abstract Data Type. Un objet dont l'utilisateur n'a absoluement rien
a savoir hormis les fonctions qui lui sont applicables (interface).



Ah. Quelque chose comme

struct adt;


Non.


Cela t'ennuierais de me (nous ?) dire pourquoi ?


typedef struct elem array[];
typedef struct list_elem list;
^^^^^^^^^


Ce n'est pas du tout ce que je veux.


Hmmm.
Tu émets un besoin. J'essaye de formuler une solution
qui y répond, à mon sens. Si c'est pas ce que tu veux,
c'est que je n'ai compris le besoin (merci de reformuler).
Mais si ce que tu veux, c'est ta solution et rien d'autre,
même si c'est minimalement différent, le dialogue va
être difficile.


Si tu y tiens,

typedef struct elem object;

Mais cela n'apporte rien, àmha.


Si.


Deuxième excuses-moi: En quoi ?

Pour etre plus clair, voici un code qui montre le probleme:
<couic>

/* pas de warnings avec ce cas
struct adt;
typedef struct adt *list;
^^^^^

typedef struct adt *array;


C'est sûr que si tu changes ma proposition, elle ne va
pas te convenir...

Pour moi, une liste (avec les sens conventionels),
c'est un objet complexe, donc implémenté par une
structure ad-hoc, et sûrement pas par un pointeur
(à la rigueur deux).


Antoine