sizeof nie zwraca wielkości zaalokowanej pamięci

0

Siemka, mam taki dziwny problem, którego nie rozumiem.

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

int main() {
	
	char *s;
	s = (char*)malloc(1024 * sizeof(char));
	printf("%d",sizeof(s));
	scanf("%[^\n]", s);
    printf("%d", sizeof(s));
	s = realloc(s, strlen(s) + 1);
    printf("%d", sizeof(s));
 
return 0;
}

Powyższy fragment kodu ma tworzyć tablicę dynamiczną, tylko ten fragment mi nie działa. Zostawiłem printfy, którymi próbowałem debbugować kod. Nie jestem w stanie zrozumieć, dlaczego niezależnie od tego, co zrobię rozmiar tworzonej tablicy to 4 (linux gcc) / 8 (DevC), a nie 4096. Niezależnie od tego, co wrzucę do malloca, zawsze rozmiarem tablicy jest 4. Bardzo się ucieszę, jeśli ktoś poświęci mi 5 minut i wytłumaczy mi mój banalny błąd (bo nie wierzę, żeby był skomplikowany) :) trochę siedzę już nad tym, pewnie nie umiem szukać, więc piszę na forum.

Pozdrawiam dX

6

sizeof ewaluuje się do wielkości wskaźnika, nie zaalokowanej pamięci. To musisz zapamiętać sam, jeśli potrzebujesz.

2

Tak jak Ci napisał @kq , sizeof zwraca rozmiar wskaźnika, a nie dynamicznie zaalokowanego obszaru. Swoją drogą, jak dokładnie szukaleś, bo pierwszy link w wyszukiwarce podaje odpowiedź:)
https://duckduckgo.com/?q=sizeof+doesn%27t+return+dynamically+allocated+memory&t=canonical&ia=web

0
kq napisał(a):

sizeof ewaluuje się do wielkości wskaźnika, nie zaalokowanej pamięci. To musisz zapamiętać sam, jeśli potrzebujesz.

Wyczytałem na wiki, zmieniałem z char* na char w nadziei, że drogą dedukcji dojdę do rozwiązania, ale niestety nie. To pozostałość po moich próbach naprawienia kodu. Dalej ten sam problem niestety :(

1

Dalej ten sam problem niestety

Nadal próbujesz jeść zupę widelcem, a on nie do tego służy ;​)

Jak chcesz wielkość alokacji to musisz ją samodzielnie zapamiętać.

0
kq napisał(a):

Dalej ten sam problem niestety

Nadal próbujesz jeść zupę widelcem, a on nie do tego służy ;​)

Jak chcesz wielkość alokacji to musisz ją samodzielnie zapamiętać.

Kurcze, nie rozumiem... co oznacza "samodzielnie zapamiętać"?
Nie za bardzo rozumiem, do czego konkretnie się odnosisz. Dla Ciebie jest to trywialne, dla mnie jeszcze nie :/

1

@kq: już podał odpowiedź (zgodną ze standardem), tym niemniej niektóre implementacje wystawiają api, które zwróci rozmiar zaalokowanego bloku przez funkcję z rodziny malloca, np. malloc_usable_size albo _msize.
Btw, jeśli piszesz w C to nie potrzebujesz castować typu zwracanego przez [m|c|re]alloc.

3

"Kurcze, nie rozumiem... co oznacza "samodzielnie zapamiętać"?" Uff, po prostu, sizeof nie rozwiąze Twojego problemu, jak bardzo Chcesz to zapamiętać, to Zrób sobie strukturkę:

struct {
    char * buff;
    size_t limit;
}

I już Masz.

3
dark_Xenio napisał(a):
kq napisał(a):

Dalej ten sam problem niestety

Nadal próbujesz jeść zupę widelcem, a on nie do tego służy ;​)

Jak chcesz wielkość alokacji to musisz ją samodzielnie zapamiętać.

Kurcze, nie rozumiem... co oznacza "samodzielnie zapamiętać"?
Nie za bardzo rozumiem, do czego konkretnie się odnosisz. Dla Ciebie jest to trywialne, dla mnie jeszcze nie :/

size_t alloc_size = 42;
char* buf = malloc(alloc_size);

Jak planujesz to często w ten sposób przekazywać to opakuj w strukturę jak @lion137 radzi.

3
typedef struct { size_t size; char * buff; } SizedBuff;
SizedBuff szalloc(size_t size)
{
	SizedBuff ret;
	ret.size=size;
	ret.buff=(char*)malloc(size);
	return ret;
}
void szfree(SizedBuff *szbuff)
{
	if(szbuff->size) free(szbuff->buff);
	szbuff->size=0;
	szbuff->buff=NULL;
}

void foo()
{
	SizedBuff szbuff=szalloc(100);

	szfree(&szbuff);
}
0
kq napisał(a):

sizeof ewaluuje się do wielkości wskaźnika, nie zaalokowanej pamięci. To musisz zapamiętać sam, jeśli potrzebujesz.

Dobra, już wszystko rozumiem xd

Zupełnie nie rozumiałem istoty mojego problemu, myślałem, że to malloc nie działa xD
Problem leżał w dalszej części programu.
Dla potomnych (może komuś się przyda), błąd w pętli: w tej postaci sizeof zwraca rozmiar 1-szego elementu tablicy, nie samej tablicy. Powinienem użyć strlen.

Fix:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>


int main() {
    
    char *s;
    size_t alloc_size = 4096;
    s = (char*)malloc(alloc_size);
    scanf("%[^\n]", s);
    s = realloc(s, strlen(s) + 1);

    for (int i=0; i < strlen(s); i++) {  // wczesniej bylo for (int i=0; i < sizeof(s); i++)
        if (s[i] == ' ') {               // co z oczywistych wzgledow nie dzialalo
            printf ("\n");
        }
        else
            printf ("%c", s[i]);
    }
    
    return 0;
}

Dziękuje Wam chłopaki bardzo za pomoc :)

2

Dla potomnych:

  • Wiekość tablicy to tyle ile podałeś w funkcji malloc czyli w twoim wypadku 4096
  • strlen zwraca wielkość C-Stringa zapisanego w tej tablicy, a dokładnie index pierwszego wystąpienia znaku '\0' zwanego także NULL

Dla @dark_Xenio:

  • Jakbyś od razu powiedział że chodzi i o iterowanie po tablicy charów prawdopodobniej ktoś szybciej odgadłby z czym masz problem :D
2
dark_Xenio napisał(a):
    for (int i=0; i < strlen(s); i++) 

Czy wiesz że strlen będzie liczony na każdym kroku pięti?

dark_Xenio napisał(a):
        if (s[i] == ' ') {               // co z oczywistych wzgledow nie dzialalo
            printf ("\n");
        }
        else
            printf ("%c", s[i]);

wystarczy

printf("%c",s[i]==' '?'\n':s[i]);
0
_13th_Dragon napisał(a):
dark_Xenio napisał(a):
    for (int i=0; i < strlen(s); i++) 

Czy wiesz że strlen będzie liczony na każdym kroku pięti?

W jaki sposób uniknąć tego? Zapisać wartość strlen w postaci

int temp = strlen(s);
for (int i=0; i < temp; ++i) 

?

dark_Xenio napisał(a):
        if (s[i] == ' ') {               // co z oczywistych wzgledow nie dzialalo
            printf ("\n");
        }
        else
            printf ("%c", s[i]);

wystarczy

printf("%c",s[i]==' '?'\n':s[i]);

Dzięki :D niezbyt dobry jestem jeszcze w C :)

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