Rozmiar tablicy znaków

0

Cześć.
Czy ktoś może mi wyjaśnić, dlaczego taki kod:

 #include <iostream>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <cstring>
 
int main()
{
    string input;
 
    cin >> input;
    int size=input.length();
 
    cout << input <<"rozmiar: "<< size << endl;
 
    char *in;
    in = new char[10];
 
    for(int i=0;i<size;++i)
    {
        in[i]=input[i];
    }
    in[size]='\0';
    cout << in <<"rozmiar: "<< sizeof(in) << endl;

 
    return 0;
}

Zawsze wypisuje rozmiar 'in' równy 4?
Podobnie dzieje się, gdy chcę to zrobić w taki sposób:

 #include <iostream>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <cstring>
 
int main()
{
    string input;
    cin >> input;
    char *in = const_cast<char*> ( input.c_str() );
    cout << in <<"rozmiar: "<< sizeof(in) << endl;

 
    return 0;
}

Pomocy..

0
Qkartka napisał(a):
    char *in;

jak widzisz twoja zmienna "in" jest zmienną wskaźnikową. Wskaźniki posiadają "stały" rozmiar (zależnie od architektury oraz kompilatora no i "rodzaju" wskaźnika - przyjmij jednak na razie że jest tak jak mówię). Odpowiedź na twoje pytania została udzielona w podobnym temacie.

0

Długość napisu zwraca ci funkcja strlen().
Ilość elementów tablicy jest jest taka jak podana w new char[10].
Rozmiar tablicy to rozmiar jednego elementu razy ilość elementów; rozmiar char wynosi 1, więc tablica ma 10 bajtów.

Dlatego uwazam, ze powinna mi tam jednak wyskoczyc 10, a nie 4.
in jest wskaźnikiem. sizeof(in) zwraca ci rozmiar wskaźnika, a nie wskazywanych danych.

0
Qkartka napisał(a):

Dlatego uwazam, ze powinna mi tam jednak wyskoczyc 10, a nie 4.

Tutaj masz taki sam problem jak autor tematu, który podlinkowałem. Pytasz dokładnie o to samo (o rozmiar tablicy dynamicznej - operator jakim to wykonujesz nie ma znaczenia), a ja ci odpowiadam dokładnie to samo co odpowiedziałem tam. Niestety źle uważasz bo wskaźnik to liczba i w zależności od kompilatora i architektury jaką posiadasz liczba ta (adresy pamięci) może być zapisana np na 32 bitach bądź 64 bitach, a więc sizeof(wskaźnik) obojętnie na jaki typ by to nie był wskaźnik zawsze zwróci rozmiar liczby, która reprezentuje miejsce w pamięci, a nie dane które się tam znajdują.

0

Może to ci trochę wyjaśni:

#include <iostream>
#include <string>
#include <cstring>
using namespace std;
 
int main()
  {
   string input;

   cin>>input;
   cout<<input<<" rozmiar: "<<input.length()<<endl;
   char *in=new char[input.length()+1];
   for(int i=0;i<input.length();++i) in[i]=input[i];
   in[input.length()]='\0';
   cout<<in<<" rozmiar:"<<strlen(in)<<endl;
   char *ar=&input[0];
   cout<<ar<<" rozmiar:"<<strlen(ar)<<endl;
   return 0;
  }
1

@robcio

Przeciez jak mamy wskaznik na inta ,na chara, czy na funkcje to jego rozmiary sa takie same w danej architekturze

Właśnie z tymi wskaźnikami na funkcje nie jest do końca tak jak mówisz, a w zasadzie z ich pewnym rodzajem - wskaźnikami na funkcje składowe (czy też metody). Te wskaźniki mogą mieć inne rozmiary niż pozostałe rodzaje wskaźników. Przykład:

#include <iostream>

using namespace std;

class Base {
    public:
        Base(){}
        virtual void foo(int){ cout << "Base::foo(int);\r\n"; }
        virtual ~Base() {}
};

class Inherited : public Base {
    public:
        Inherited() : Base() {}
        void foo(int) { cout << "Inherited::foo(int);\r\n"; }
        void foo2() { cout << "Inherited::foo2();\r\n"; }
};

void foo(int, int) { cout << "foo(int, int);\r\n"; }

typedef void (*PFoo)(int, int);
typedef void (Base::*PBaseFoo)(int);
typedef void (Inherited::*PInheritedFoo)(int);
typedef void (Inherited::*PInheritedFoo2)();

int main()
{
    PFoo pf = &foo;
    PBaseFoo pbf = &Base::foo;
    PInheritedFoo pif = &Base::foo;
    PInheritedFoo pif2 = &Inherited::foo;
    PInheritedFoo2 pif3 = &Inherited::foo2;

    Base *b1 = new Base();
    Base *b2 = new Inherited();
    Base b3;
    Inherited *i1 = new Inherited();
    Inherited i2;

    //przy okazji przykład użycia
    cout << "(*pf) : "; (*pf)(0, 0);
    cout << "(b1->*pbf) : "; (b1->*pbf)(1);
    cout << "(b2->*pbf) : "; (b2->*pbf)(2);
    cout << "(b3.*pbf) : "; (b3.*pbf)(3);
    cout << "(i1->*pbf) : "; (i1->*pbf)(4);
    cout << "(i1->*pif) : "; (i1->*pif)(5);
    cout << "(i1->*pif2) : "; (i1->*pif2)(6);
    cout << "(i1->*pif3) : "; (i1->*pif3)();
    cout << "(i2.*pbf) : "; (i2.*pbf)(7);
    cout << "(i2.*pif) : "; (i2.*pif)(8);
    cout << "(i2.*pif2) : "; (i2.*pif2)(9);
    cout << "(i2.*pif3) : "; (i2.*pif3)();

    //rozmiary
    cout << "\r\nsizeof(int*) = " << sizeof(int*)
         << "\r\nsizeof(PFoo) = "   << sizeof(PFoo)
         << "\r\nsizeof(PBaseFoo) = "  << sizeof(PBaseFoo)
         << "\r\nsizeof(PInheritedFoo) = "  << sizeof(PInheritedFoo)
         << "\r\nsizeof(PInheritedFoo2) = " << sizeof(PInheritedFoo2);

    delete i1;
    delete b2;
    delete b1;

    return 0;
}

w moim przypadku (windows xp 32 bit + mingw32(z gcc 4.4.1)) powyższy kod daje następujące wyjście:

(*pf) : foo(int, int);
(b1->*pbf) : Base::foo(int);
(b2->*pbf) : Inherited::foo(int);
(b3.*pbf) : Base::foo(int);
(i1->*pbf) : Inherited::foo(int);
(i1->*pif) : Inherited::foo(int);
(i1->*pif2) : Inherited::foo(int);
(i1->*pif3) : Inherited::foo2();
(i2.*pbf) : Inherited::foo(int);
(i2.*pif) : Inherited::foo(int);
(i2.*pif2) : Inherited::foo(int);
(i2.*pif3) : Inherited::foo2();

sizeof(int*) = 4
sizeof(PFoo) = 4
sizeof(PBaseFoo) = 8
sizeof(PInheritedFoo) = 8
sizeof(PInheritedFoo2) = 8

Poza tym wskaźniki na funkcje mogą mieć różne rozmiary w zależności od wykorzystywanej architektury - czy to architektury harwardzkiej czy von Neumana bądź mieszanej. Są to specyficzne zastosowania jednak nie można stwierdzić, że ten rodzaj wskaźników posiada zawsze taki sam rozmiar jak pozostałe rodzaje, a tym bardziej nie polecałbym na tym bazować bo kiedyś można się przejechać.
Sądzę, że jest to również jeden z powodów dla których standard nie gwarantuje iż void* przechowa wskaźnik na dowolną funkcję przez co należy taką operację uznać za zachowanie niezdefiniowane.

0

Poza tym wskaźniki na funkcje mogą mieć różne rozmiary w zależności od wykorzystywanej architektury - czy to architektury harwardzkiej czy von Neumana bądź mieszanej.

Nawet w x86 są dwa rodzaje wskaźników: bliskie (near) - 16 lub 32 bity, i dalekie (far) - 32 lub 48 bitów.
W 16-bitowych programach wskaźnik bliski obejmował tylko 64 kilobajty pamięci, dlatego używano obu rodzajów.
W 32 bitach nie ma już takiego ograniczenia, i używa się tylko wskaźników bliskich (chyba że w asemblerze, oprogramowaniu systemowym itp.)
W 64 bitach segmentacja została dodatkowo okastrowana, tak że dalekie wskaźniki nie mają już sensu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1