Puntatori bella domanda!

di il
9 risposte

Puntatori bella domanda!

Vorrei sottoporvi un problema
come si fa a capire se un puntatore sta puntando ad una variabile stringa o ad una varibile numerica ,quale int double etc etc, o ad una struct o ad una funzione?

9 Risposte

  • Re: Puntatori bella domanda!

    Prendi ad esempio questo pseudocodice C:

    ind_dato=&dato2;

    Questa istruzione assegna a ind_dato non il contenuto di dato2, ma l'indirizzo di memoria dove dato2 è contenuta. Quindi ind_dato punta a dato e affinché l'assegnazione di sopra sia lecita ind_dato deve essere definito come puntatore allo stesso tipo di dato2.
  • Re: Puntatori bella domanda!

    smalldragon ha scritto:


    vorrei sottoporvi un problema
    come si fa a capire se un puntatore sta puntando ad una variabile stringa o ad una varibile numerica ,quale int double etc etc, o ad una struct o ad una funzione?
    Immagino partendo da un 'void*' ?
    Non si puo'. Piu' o meno.

    I puntatori sono di tipo T*, dove T e' uno dei tipi nativi o (int, double,...) o una struct/class.

    Si puo' fare qualcosa se T e' una struct/class ed e' abilitato il supporto al RTTI (Run Time Type Information), nel qual si puo' utilizzare il dynamic_cast<> ed il reinterpret_cast<>.

    Comunque, ci sono due cose che in C++ non si dovrebbero (non che 'NON SI DEVONO') mai fare:

    1) non sapere di che tipo e' un puntatore
    2) modificare il valore di un puntatore.
  • Re: Puntatori bella domanda!

    migliorabile ha scritto:


    I puntatori sono di tipo T*, dove T e' uno dei tipi nativi o (int, double,...) o una struct/class.
    ok fino a quà ci ero arrivato.
    ma ad un certo punto il sistema dovrà pur riconoscere il tipo al fine di poter effettuare l'operazione corretta per quel determinato tipo di puntatore o segnalare l'errore perchè l'operazione non si può fare con quel determinato tipo di puntatore.
    bene io vorrei capire come fa!
  • Re: Puntatori bella domanda!

    http://msdn.microsoft.com/it-it/library/fyf39xec.asp
  • Re: Puntatori bella domanda!

    Grazie skynet per la risoluzione pratica.
    ma se volessi realizzare una routine che fa quello che fa la typeid come posso fare?
    dove posso trovare un pò di teoria sull'argomento?
    sto cercando per quanto e possibile di svincolarmi dalle librerie non mie.
  • Re: Puntatori bella domanda!

    A prescindere da skynet,se tu stai scrivendo il codice,tu sai che cosa punta il puntatore!
    Tu hai creato il puntatore e solo tu hai creato l'assegnazione e quindi penso tu sappia bene a cosa stia puntando.

    Se devi creare un puntatore generico allora devi crearti una variabile che indichi cosa esso contenga in base alle specifiche del tuo programma:
    
    
    typedef struct _VARIANTPTR
    {
        void* var;
        unsigned int size;
    }VARIANTPTR;
    
    int main()
    {
        int a=970;
        double b=999.25;
    
        VARIANTPTR c[2];
                   c[0].var=&a;
                   c[0].size=sizeof(a);
                   c[1].var=&b;
                   c[1].size=sizeof(b);
    
        int i;
        for (i=0; i < 2 ; i++)
        {
            if (c[i].size == 4)
            {
                printf ("c[%d]==%d\n",i,*((int*)c[i].var));
            }
            else if (c[i].size == 8)
            {
                printf ("c[%d]==%lf\n",i,*((double*)c[i].var));
            }
        }
    
        return 0;
    }
    
    naturalmente una lettura al typeinfo.h non farebbe male:
    
    // RTTI support for -*- C++ -*-
    // Copyright (C) 1994, 1995 Free Software Foundation
    
    // This file is part of the GNU ANSI C++ Library.  This library is free
    // software; you can redistribute it and/or modify it under the
    // terms of the GNU General Public License as published by the
    // Free Software Foundation; either version 2, or (at your option)
    // any later version.
    
    // This library is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    // GNU General Public License for more details.
    
    // You should have received a copy of the GNU General Public License
    // along with this library; see the file COPYING.  If not, write to the Free
    // Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    
    // As a special exception, if you link this library with files
    // compiled with a GNU compiler to produce an executable, this does not cause
    // the resulting executable to be covered by the GNU General Public License.
    // This exception does not however invalidate any other reasons why
    // the executable file might be covered by the GNU General Public License.
    
    // Written by Kung Hsu based upon the specification in the 20 September 1994
    // C++ working paper, ANSI document X3J16/94-0158.
    
    #ifndef __TYPEINFO__
    #define __TYPEINFO__
    
    #ifdef __GNUG__
    #pragma interface "std/typeinfo.h"
    #endif
    
    extern "C" void* __throw_type_match_rtti (void *, void *, void *);
    
    extern "C++" {
    class type_info {
    private:
      // assigning type_info is not supported.  made private.
      type_info& operator=(const type_info&);
      type_info(const type_info&);
    
    public:
      enum node_type {
        _RTTI_BUILTIN_TYPE,               // builtin type
        _RTTI_USER_TYPE,                  // user defined type
        _RTTI_CLASS_TYPE,                 // class type
        _RTTI_POINTER_TYPE,               // pointer type
        _RTTI_ATTR_TYPE,                  // attribute type for const and volatile
        _RTTI_FUNC_TYPE,                  // function type
        _RTTI_PTMF_TYPE,                  // pointer to member function type
        _RTTI_PTMD_TYPE                   // pointer to member data type
        };
    
      // return node type of the object
      virtual node_type __rtti_get_node_type() const { return _RTTI_BUILTIN_TYPE; }
    
      // get_name will return the name of the type, NULL if no name (like builtin)
      virtual const char * __rtti_get_name() const { return 0; }
    
      // compare if type represented by the type_info are the same type
      virtual int __rtti_compare(const type_info&) const { return 0; }
    
      // argument passed is the desired type, 
      // for class type, if the type can be converted to the desired type, 
      // it will be, and returned, else 0 is returned.  If the match
      // succeeds, the return value will be adjusted to point to the sub-object.
      virtual void* __rtti_match(const type_info&, int, void *) const {
        // This should never be called.
        return 0;
      };
    
      // destructor
      virtual ~type_info() {}
      type_info() {}
        
      bool before(const type_info& arg);
      const char* name() const
        { return __rtti_get_name(); }
      bool operator==(const type_info& arg) const 
        { return __rtti_compare(arg) == 0; }
      bool operator!=(const type_info& arg) const 
        { return __rtti_compare(arg) != 0; }
    };
    
    // type_info for builtin type
    
    class __builtin_type_info : public type_info {
    public:
      enum builtin_type_val {
        _RTTI_BI_BOOL = 1, _RTTI_BI_CHAR, _RTTI_BI_SHORT, _RTTI_BI_INT, 
        _RTTI_BI_LONG, _RTTI_BI_LONGLONG, _RTTI_BI_FLOAT,
        _RTTI_BI_DOUBLE, _RTTI_BI_LDOUBLE, _RTTI_BI_UCHAR, 
        _RTTI_BI_USHORT, _RTTI_BI_UINT, _RTTI_BI_ULONG,
        _RTTI_BI_ULONGLONG, _RTTI_BI_SCHAR, _RTTI_BI_WCHAR, _RTTI_BI_VOID
      };
    
      builtin_type_val b_type;
    
      __builtin_type_info (builtin_type_val bt) : b_type (bt) {}
      node_type __rtti_get_node_type () const
        { return _RTTI_BUILTIN_TYPE; }
      const char *__rtti_get_name () const
        { return (const char *)0; }
      int __rtti_compare (const type_info& arg) const
        { return (arg.__rtti_get_node_type () == _RTTI_BUILTIN_TYPE && 
    	      ((__builtin_type_info&)arg).b_type == b_type) ? 0 : -1; }
    };
    
    // serice function for comparing types by name.
    
    inline int __fast_compare (const char *n1, const char *n2) {
      int c;
      if (n1 == n2) return 0;
      if (n1 == 0) return *n2;
      else if (n2 == 0) return *n1;
    
      c = (int)*n1++ - (int)*n2++;
      return c == 0 ? strcmp (n1, n2) : c;
    };
    
    // type_info for user type.
    
    class __user_type_info : public type_info {
     private:
      const char *_name;
    
    public:
      __user_type_info (const char *nm) : _name (nm) {}
      node_type __rtti_get_node_type () const
        { return _RTTI_USER_TYPE; }
      const char *__rtti_get_name () const
        { return _name; }
      int __rtti_compare (const type_info& arg) const
        { return (arg.__rtti_get_node_type () == __rtti_get_node_type() &&
    	__fast_compare (_name, arg.__rtti_get_name ()) == 0) ? 0 : -1; }
    };
    
    // type_info for a class.
    
    class __class_type_info : public __user_type_info {
    private:
      enum access_mode {
        _RTTI_ACCESS_PUBLIC, _RTTI_ACCESS_PROTECTED, _RTTI_ACCESS_PRIVATE
        };
      type_info **base_list;
      int *offset_list;
      int *is_virtual_list;
      access_mode *access_list;
      int n_bases;
    
    public:
      __class_type_info (const char *name, type_info **bl, int *off, 
    		     int *is_vir, access_mode *acc, int bn)
        : __user_type_info (name), base_list (bl), offset_list(off), 
          is_virtual_list(is_vir), access_list(acc), n_bases (bn) {}
      node_type __rtti_get_node_type () const
        { return _RTTI_CLASS_TYPE; }
    
      // inherit __rtti_compare from __user_type_info
    
      // This is a little complex defined in typeinfo.cc
      void* __rtti_match(const type_info&, int, void *) const;
    };
    
    // type info for pointer type.
    
    class __pointer_type_info : public type_info {
    private:
      type_info& type;
    
    public:
      __pointer_type_info (type_info& ti) : type (ti) {}
      node_type __rtti_get_node_type () const
        { return _RTTI_POINTER_TYPE; }
      const char *__rtti_get_name () const
        { return (const char *)0; }
      int __rtti_compare (const type_info& arg) const
        { return (arg.__rtti_get_node_type () == __rtti_get_node_type() &&
    	type.__rtti_compare ( ((__pointer_type_info&)arg).type) == 0) ? 0 : -1; }
      void* __rtti_match(const type_info& catch_type, int, void *objptr) const;
    };
    
    // type info for attributes
    
    class __attr_type_info : public type_info {
    public:
      enum attr_val {
        _RTTI_ATTR_CONST = 1, _RTTI_ATTR_VOLATILE, _RTTI_ATTR_CONSTVOL
        };
    
      attr_val attr;
      type_info& type;
    
      __attr_type_info (attr_val a, type_info& t) : attr (a), type(t) {}
      node_type __rtti_get_node_type () const
        { return _RTTI_ATTR_TYPE; }
      const char *__rtti_get_name () const
        { return (const char *)0; }
      int __rtti_compare (const type_info& arg)  const
        { return (arg.__rtti_get_node_type () == _RTTI_ATTR_TYPE && 
    	      attr == ((__attr_type_info&)arg).attr &&
    	      type.__rtti_compare ( ((__attr_type_info&)arg).type ) == 0) 
    	      ? 0 : -1; }
    };
    
    // type info for function.
    
    class __func_type_info : public __user_type_info {
    public:
      __func_type_info (const char *name) : __user_type_info (name) {}
      node_type __rtti_get_node_type () const
        { return _RTTI_FUNC_TYPE; }
    };
    
    // type info for pointer to member function.
    
    class __ptmf_type_info : public __user_type_info {
    public:
      __ptmf_type_info (const char *name) : __user_type_info (name) {}
      node_type __rtti_get_node_type () const
        { return _RTTI_PTMF_TYPE; }
    };
    
    // type info for pointer to data member.
    
    class __ptmd_type_info : public type_info {
      type_info& classtype;
      type_info& type;
    public:
      __ptmd_type_info (type_info& tc, type_info& t) : classtype (tc), type (t) {}
      node_type __rtti_get_node_type () const
        { return _RTTI_PTMD_TYPE; }
      int __rtti_compare (const type_info& arg)  const
        { return (arg.__rtti_get_node_type () == _RTTI_PTMD_TYPE && 
    	classtype.__rtti_compare ( ((__ptmd_type_info&)arg).classtype ) == 0 &&
    	type.__rtti_compare ( ((__ptmd_type_info&)arg).type ) == 0) 
    	      ? 0 : -1; }
    };
    } // extern "C++"
    
    #include <stdexcep>
    
    #endif
    
  • Re: Puntatori bella domanda!

    Alternativa:
    leggi la documentazione di boost::any della libreria Boost.

    Per conoscere il tipo di un puntatore non basta conoscere la dimensione dell'oggetto puntato, ovviamente.

    Svincolarsi dalle librerie non e' mai saggio.
    Vuol dire reinventare la ruota.
    In questo caso e' peggio: typeid e' una keyword del c++, per la precisione un operatore. Le strutture dati a cui si appoggia sono generate direttamente in fase di compilazione.

    Per svincolarti, dovresti poter estendere il compilatore, e aggiungere il supporto al reflection (che cosa e' il reflection?)

    Altra alternativa e' inventarti un 'tuo' tipo puntatore: un cosidetto 'smart pointer' (come si fa?)

    Come punto di partenza studiati gli 'Smart Pointer' di Boost (si, sempre lei )

    Con una massiccia iniezione di template, si puo' fare.
  • Re: Puntatori bella domanda!

    Per quanto riguarda il fatto che il sistema sia in grado di capire se puo' o meno eseguire un'operazione, ti sfugge un fatto: il c++ tenta SEMPRE di eseguire l'operazione e schiatta solo se le strutture di servizio a cui tenta di accedere risultano corrotte.

    Ad esempio:

    int i = *(int*) (void*) ("io sono una stringa") ;

    compila tranquillamente ed 'i' puo' essere usato tranquillamente come intero!

    Un esempio classico di struttura dati di servizio e' la virtual table dei metodi.
  • Re: Puntatori bella domanda!

    Grazie a tutti per le informazioni
    ho parecchio da studiare e grazie alle vostre informaioni con il passare del tempo riusirò a realizzare il mio proggetto.

    migliorabile ha scritto:


    Vuol dire reinventare la ruota.
    per quanto riguarda la reinvenzione della ruota se non fosse stata reinventata nei secoli a quest' ora
    avremo fabbricato ancora le ruote di pietra e quindi non avremo potuto inventare le automobili a meno che per farle muovere non avessimo usato l'energia atomica.
    ed ad ogni incidente avremmo rischiato l'etinzione!
    morale se non ci reinventiamo e miglioriamo le basi come facciamo ad evolverci!
Devi accedere o registrarti per scrivere nel forum
9 risposte