La copie de tableau facile, a portée de main ?

La copie de tableau facile, a portée de main ? - C++ - Programmation

Marsh Posté le 21-09-2002 à 01:46:00    

Note: Je vous fait grâce ici des assertions et vérifications de tailles.

Code :
  1. //Commençons en C, et prenons des tableaux:
  2. int    tab1[7];
  3. int    tab2[7];
  4. int    tabx[10];
  5. double tabd[7];
  6. //Ni C, ni C++ ne permettent l'affectation:
  7. tab1= tab2; //impossible
  8. //Le truc classique, c'est d'utiliser memcpy
  9. memcpy( tab1, tab2, sizeof(tab1) );
  10. //Que je m'empresses d'emballer dans une macro
  11. #define ARRAYCPYFAST(dst,src) ( memcpy( dst, src, sizeof(dst)) )
  12. //Mais ce n'est pas sécurisé du tout !
  13. ARRAYCPYFAST(tab1, tabd); //oups, représentations et tailles différentes


 
Considérant le cas des types différents, et celui des types C++ surchargeant l'opérateur '=', il faut bien faire une affectation membre-à-membre:

Code :
  1. #define DIMOF(a) (sizeof(a)/sizeof(a)[0])
  2. #define ARRCPYSURE(dst,src) for(ptrdiff_t i= DIMOF(dst)-1 ; i>=0 ; --i)\
  3.                                   (dst)[i]= (src)[i] ;}while(0)
  4. //C'est encore une macro.
  5. //Je voudrais avoir la sécurité et le confort d'une fonction, mais...
  6. //Quand on transmet un tableau à une fonction, elle ne reçoit qu'un pointeur sur son premier élément, et on perd l'information de taille.
  7. f(tab); //appelles 'f(int *)' ou 'f(int [])', c'est kif-kif
  8. //Donc, galère:
  9. arrcpybof(int*,int*,size_t);
  10. arrcpybof(tab1,tab2,DIMOF(tab1)); //copie sans contrôle de taille possible
  11. //Mais tout n'est pas perdu.
  12.   tab1   ; //type 'int [7]'
  13.   tab1[n]; //type 'int'
  14. &tab1[n]; //type 'int*'
  15. f(tab1)  ; //type 'int*' (&tab[0] implicite en expression)
  16. &tab1   ; //type 'int(*)[7]'. Un pointeur de tableau dimensionné, voilà qui est intéressant !
  17. void arrcpyptr(int(* const pdst)[7] , const int(* const psrc)[7]){
  18. for (ptrdiff_t i= 6 ; i>=0 ; --i)  (*pdst)[i]= (*psrc)[i];
  19. }
  20. arrcpyptr(&tab1,&tab2); //copie sûre


 
Seulement, on a perdu la généricité, on ne copie que des 'int[7]', et l'appel n'est pas naturel.
 
Entrons de plein-pied dans le C++ maintenant.

Code :
  1. //Si je peut en prendre un pointeur, je peut en prendre une référence !
  2. void arrrcpyref(int(&rdst)[7] , const int(&rsrc)[7]){
  3. for (ptrdiff_t i= 4 ; i>=0 ; --i)  rdst[i]= rsrc[i];
  4. }
  5. arrcpyref(tab1,tab2); //copie sûre, appel simple
  6. //Pour la généricité, C++ dispose des patrons:
  7. template <typename dstT, typename srcT, ptrdiff_t dim>
  8. void arrrcpy(dstT (&rdst)[dim] , const srcT (&rsrc)[dim]){//'error C2265: '<Unknown>' : reference to a zero-sized array is illegal'
  9. for (ptrdiff_t i= 4 ; i>=0 ; --i)  rdst[i]= rsrc[i];
  10. }
  11. arrcpy(tab1,tabd); //Oh non ! Si près du but...


 
Visiblement, mon compilateur ne comprends pas une valeur paramètre de patron comme dimension de tableau dans un type. Unknown error  :sarcastic:  :(  :D.
Pour ne pas le nommer, c'est Visual C++ 6 sp 5, et il faut vraiment que je pense à en changer.
 
Je sais pas si c'est censé pouvoir marcher, mais ce serait tellement bien...
Donc, la suite, c'est vous qui allez l'écrire:
 
 
SVP, essayez ce dernier patron sur vos systèmes, et dites-moi si ça marche, et sinon quel message d'erreur est généré.


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 21-09-2002 à 01:46:00   

Reply

Marsh Posté le 21-09-2002 à 01:47:32    

Pour les curieux, voici mon source C 'arraytools.h' complet:

Code :
  1. //Help macros for aggregates (array or structure)
  2. //Parts are for C++
  3. //Doesn't pretend to be standard compliant, portable, fully protected, or bugless.
  4. //Required
  5. #include <memory.h>
  6. #include <stddef.h>
  7. #include <assert.h>
  8. #ifndef MIN
  9. #define MIN(a,b) ((a)<(b)?(a):(b))
  10. #endif
  11. //Test if argument is an array, not a pointer or address
  12. //array  : returns 1/true (string litterals are arrays)
  13. //pointer: returns 0/false
  14. //litteral: error '&' on constant
  15. //other   : error subscript requires array or pointer type
  16. #define ISARRAY(a) ( (char*)&(a)==(char*)&(a)[0] )
  17. //#define ISPOINTER(p) ???
  18. //#define ISADDRESS(p) ???
  19. //#define ISSTRUCT(p)  ???
  20. //Number of array elements
  21. #define DIMOF(a) ( assert(ISARRAY(a)) ,\
  22.                    sizeof(a)/sizeof(a)[0] )
  23. //Byte-wise compares any two instances (including aggregates) of same size.
  24. //Not reliable on structures with holes (allignment spacing).
  25. //May not match arithmetic ordering.
  26. //<0: i1 less    than i2  
  27. // 0: i1 identical to i2  
  28. //>0: i1 greater than i2  
  29. #define BYTECOMPARE(i1,i2) (assert(sizeof(i1)==sizeof(i2)),\
  30.                                  memcmp(&(i1), &(i2), sizeof(i1)))
  31. //True if any two instances (including aggregates) of same size are byte-wise identical.
  32. //Not reliable on structures with holes (allignment spacing).
  33. #define BYTEEQUAL(i1,i2) (BYTECOMPARE(i1,i2)==0)
  34. //Sets all bytes of any instance (including aggregates) to 0.
  35. //May not suit floating-point or C++ allocating types
  36. #define BYTEZEROFILL(a) memset(&(a),0,sizeof(a))
  37. //Sets all the elements of array to value.
  38. #define ARRAYFILL(array,value) do{assert(ISARRAY(array));\
  39.                                for(ptrdiff_t i= DIMOF(array)-1 ; i>=0 ; --i)\
  40.                                     (array)[i]= value;}while(0)
  41. //True if arrays have same dimensions, element sizes, and byte-wise content.
  42. #define ARRAYEQUALFAST(a1,a2) (assert( ISARRAY(a1) && ISARRAY(a2) && sizeof(a1)[0]==sizeof(a2)[0] ),\
  43.                              BYTEEQUAL(a1,a2))
  44. //The following come in 2 versions each:
  45. //fast  : expression, doesn't suit C++ allocating types. MAY only be faster.
  46. //normal: statement , can work with different destination & source types.
  47. //(result is undefined if areas overlap !)
  48. //Copy n array elements from src into dst (arrays or pointers)
  49. #define ARRAYCOPYN(dst,src,n) do{for(ptrdiff_t i= (n)-1 ; i>=0 ; --i)\
  50.                                   (dst)[i]= (src)[i] ;}while(0)
  51. #define ARRAYCOPYNFAST(dst,src,n) ( assert(sizeof(src)[0]==sizeof(dst)[0]) ,\
  52.                                     memcpy( dst, src, (n) * sizeof (src)[0] ) )
  53. //Copy array elements...
  54. //...from srcfirst included (array or pointer)...
  55. //...to   srcafter excluded (pointer on same array as srcfirst)...
  56. //...into dst               (array or pointer).
  57. #define ARRAYCOPYRANGE(dst,srcfirst,srcafter)     ARRAYCOPYN    ( dst, srcfirst, (srcafter)-(srcfirst) )
  58. #define ARRAYCOPYRANGEFAST(dst,srcfirst,srcafter) ARRAYCOPYNFAST( dst, srcfirst, (srcafter)-(srcfirst) )
  59. //Copy src to dst (both arrays of same dimension)
  60. #define ARRAYCOPY(dst,src)   do{ assert(ISARRAY(dst) && ISARRAY(src) && DIMOF(src)==DIMOF(dst)) ;\
  61.                                  ARRAYCOPYN    (dst, src, DIMOF(src));}while(0)
  62. #define ARRAYCOPYFAST(dst,src) ( assert(ISARRAY(dst) && ISARRAY(src) && DIMOF(src)==DIMOF(dst)) ,\
  63.                                  ARRAYCOPYNFAST(dst, src, DIMOF(src)) )
  64. //Copy src to dst (both arrays), using max safe number of elements
  65. //#ifdef __cpluplus
  66. #define ARRAYCOPYAUTO(dst,src)     ARRAYCOPYN    ( dst, src, MIN(DIMOF(src), DIMOF(dst)) )
  67. #define ARRAYCOPYAUTOFAST(dst,src) ARRAYCOPYNFAST( dst, src, MIN(DIMOF(src), DIMOF(dst)) )


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 21-09-2002 à 02:27:00    

Musaran a écrit a écrit :

Je sais pas si c'est censé pouvoir marcher, mais ce serait tellement bien...


j'ai vc6 donc ...
 
par contre, j'ai google :  
 
http://216.239.39.100/search?q=cac [...] n&ie=UTF-8
 
http://groups.google.com/groups?hl [...] 26tab%3Dwg
 
//
 
ceci dit, je ne vois pas bien où tu veux en venir avec tes macros ...

Reply

Marsh Posté le 22-09-2002 à 03:19:45    

Le but est de permettre de copier facilement des tableaux, et de façon sûre.
C'était pour montrer à quel point la solution en C est tordue et partielle.
 
C'est marrant, il y a une erreur dans le premier lien:

Citation :

...nonconstant bounds.

Au contraire, il faut une constante...
 
 
Bon ,je continues mon exploration:

Code :
  1. //Destiné à permettre de manipuler les tableaux C comme de vrais objets (très incomplet)
  2. template <typename t_elem_t, size_t t_dim>
  3. class arrhndl{
  4. t_elem_t(&m)[t_dim];
  5. public:
  6. arrhndl(t_elem_t(&arg)[t_dim]):m(arg){}
  7. arrhndl& operator= (const t_elem_t(&that)[t_dim]){
  8.  for (ptrdiff_t i= t_dim ; i>=0 ; --i)
  9.   m[i]= that[i];
  10.  return *this;
  11. }
  12. };
  13. tab1= tab2; //toujours impossible, tab1 n'est pas converti en arrhndl
  14. arrhndl tabh(tab1); //impossible...
  15. arrhndl<int,7>tabh(tab1); //...il faut préciser les paramètres d'une classe patron.
  16. tabh= tab1; //copie ? (conversion automatique de tab1 en arrhndl ?)
  17. arrhndl<int,5>tabh(tab1) = tab1; //version directe ?

Là non plus ,je ne peux pas tester.
Qu'en est-il ?
 
Mais de toutes façons, c'est plus compliqué qu'un simple appel de 'arrcpy'.
 
Ce qu'il faudrait, c'est présenter l'opérateur '=' comme une fonction indépendante à 2 arguments 'arrhndl'.
De cette façon, les tableaux C seraient peut-être automatiquement promus en 'arrhndl'.
Or justement, cet opérateur ne peut être que membre.
 
Qu'à cela ne tienne, imitons la STL et détournons '<<' de son sens premier:

Code :
  1. template <typename t_elem_t, size_t t_dim>
  2. void operator<<(array_handler<t_elem_t,t_dim> lh, array_handler<t_elem_t,t_dim> rh){
  3. lh= rh;
  4. }
  5. tab1 << tab2; // ?

Qu'en est-il ?
 
Si cela marche, alors on pourrait même copier des tableaux imbriqués, assigner en série, et plus encore.


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed