logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[C] - Sprintf i przekazywanie const char* do funkcji, problem z nazwą pliku

PeQ13 27 Sie 2013 11:01 1743 6
REKLAMA
  • #1 12672640
    PeQ13
    Poziom 10  
    Posty: 12
    Mam problem z funkcją sprintf, a konkretnie z inną funkcją która przyjmuje za jeden z argumentów const char*. Najpierw fragment kodu dla wyjaśnienia:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Tu wszystko jest fajnie, wyrzuca mi ładny napis. Problem jest w tym, że mam dalej funkcję, w stylu:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    której chciałbym użyć w ten sposób

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Ale nie działa, wrzuca mi jakiś śmieć w nazwie i tyle. Z kolei coś w stylu

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    działa... Gdzie popełniam błąd?
  • REKLAMA
  • Pomocny post
    #2 12672972
    beluosus
    Poziom 25  
    Posty: 362
    Pomógł: 123
    Ocena: 18
    15 to za mało, powinno być 16 żeby null-terminator się zmieścił.

    PS
    Przy liczniku > 9999 i tak się popsuje.
  • REKLAMA
  • Pomocny post
    #3 12673193
    przemko07
    Poziom 16  
    Posty: 161
    Pomógł: 24
    Ocena: 4
    to skoro padła odpowiedz jak poradzić sobie z problemem to powiem co poszło nie tak.
    w językach kompilowanych, na przykład C oprócz zwykłej tablicy istnieje także statyczna czysta tablica.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    gdzie liczba to naprzykład
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    podczas przejścia preprocesora jak kompilator widzi zapis
    char liczba[10];
    to nie wolno zakładać ze stworzy się 11 elementów(dodatkowy null na końcu)
    nie wolno też zakładać że tablica będzie w 2 miejscach(wskaźnik na stosie i reszta na stercie).
    kompilator będzie tak skracał, dopracowywał kod że będzie traktował czasami taką tablice jak kilka zmiennych, i zapis
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    zwróci ilość elementów, czego nie da się zrobić z tablicami dynamicznymi.
    porostu podczas działania preprocesora jak gdzieś natrafi się zapis
    tablica[3]
    to wcale od poziomu assemblera nie musi być odwołanie do tablicy, tylko do konkretnego miejsca. tak jest w przypadku całkowicie jawnych tablic, gdzie wiadomo jaka wielkość w trakcie kompilacji.
    jeśli rzutujesz sobie tablice const char[] na const* char to kompilator nie ma żadnych szans żeby poznać wielkość takiej tablicy,
    const* char to wskaźnik
    natomiast
    const char[] to tablica
    to byłoby jedno i to samo gdyby nie optymalizacja kodu kompilatora.
    w twoim przypadku wystąpiła jeszcze jedna rzecz printf będzie tak długo wypisywał ciąg bajtów aż nie trafi na pusty bajt(null),
    jeśli kompilator podczas kompilacji zauważył statyczna tablice i wiedział ile ma dokładnie miejsca za alokować to nie alokował dodatkowego bajtu na null'a, bo w dalszej pracy i tak będzie wiedział jaki jest rozmiar takiej tablicy.
    podczas gdy ty rzutowałeś na const char* program w runtime nie był już w stanie określić wielkości tablicy.
  • REKLAMA
  • #4 12673203
    PeQ13
    Poziom 10  
    Posty: 12
    Ok, dziękuję za odpowiedź, rzeczywiście problem tkwił w rozmiarze tablicy, Do zamknięcia :)
  • #5 12674779
    stanleysts
    Poziom 27  
    Posty: 838
    Pomógł: 115
    Ocena: 2
    Cytat:
    na przykład C oprócz zwykłej tablicy istnieje także statyczna czysta tablica.

    Co to ma wspólnego z kodem który wrzuciłeś?

    Cytat:
    nie wolno też zakładać że tablica będzie w 2 miejscach(wskaźnik na stosie i reszta na stercie).

    Tablica jak powyżej nie trzyma nigdy żadnego wskaźnika, tylko liczba_elementów * rozmiar_elementu.

    Cytat:
    const* char
    Chyba const char* xxx albo char * const xxx, nie wiem co chciałeś osiągnąć. Prawdopodobnie to pierwsze.

    Cytat:
    jeśli kompilator podczas kompilacji zauważył statyczna tablice i wiedział ile ma dokładnie miejsca za alokować to nie alokował dodatkowego bajtu na null'a, bo w dalszej pracy i tak będzie wiedział jaki jest rozmiar takiej tablicy.


    Powodzenia w C-stringach robić coś takiego, zawsze ma być taka tablica, żeby się null-terminator zmieścił i koniec. Inaczej wychodzą dziwy.
  • #6 12677421
    przemko07
    Poziom 16  
    Posty: 161
    Pomógł: 24
    Ocena: 4
    1)
    jest różnica pomiedzy wielkością tablic (tablica1, tablica2) jeśli:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    jeśli już nawet pozwoli skompilować drugim sposobem to tylko dzięki nowemu standardowi.

    2)
    tablica statyczna to czasami tylko miejsce na stosie. wiec będzie mieć n elementów
    tablica dynamiczna to n elementów + wskaźnik który wskazuje na tablice

    3)
    racja, pomyliłem się.

    4)
    sprawa optymalizacji kodu jest trochę nieprzewidywalna.
    czasmi po #definie stworzy Ci się tylko blok elementów a czasami tablica statyczna. nikt nie mówi że należy korzystać tylko z bloku elementów, ale należy wiedzieć że optymalizacja kodu czasami może nam popsuć coś co wygląda dobrze ze strony kodu.

    przykładowo.

    Kod: text
    Zaloguj się, aby zobaczyć kod


    w momencie wyliczania
    s1 zostają podstawione same stałe,
    a w momencie Convert(array) za array zostaje podstawiona liczba która oznacza wskaźnik ale to nie oznacza że ten wskaźnik gdzieś istnieje, została podstawiona zwykła liczba bo była już znana przed runtime.
  • REKLAMA
  • #7 12677577
    stanleysts
    Poziom 27  
    Posty: 838
    Pomógł: 115
    Ocena: 2
    Piszesz bardzo nieprecyzyjnie:
    1) jesli podajesz, pod spodem, że "liczba" to #define liczba XX, to nie dziw się, że nie rozumiem co chcesz powiedzieć, bo dla mnie to zwykła tablica o stałej wartości, jakbyś napisał, że to zmienna to od razu byłaby inna gadka.
    Wystarczyło napisaćł: rozmiar tablicy może być tylko stały (więc albo przez #define XX albo const int XX), albo nowe standardy pozwalają na robienie tego jako zmienna.
    A nie tak jak piszesz wcześniej.

    2). jeśli piszesz o wskaźniku to napisz, że chodzi o dynamiczną tablicę a nie w dalszym ciągu o zwykłą.

    4). Całkowicie nie o tym mówię.

Podsumowanie tematu

✨ Użytkownik napotkał problem z funkcją sprintf w języku C, która generuje nazwę pliku, a następnie przekazuje ją do innej funkcji jako argument const char*. Okazało się, że problem wynikał z niewłaściwego rozmiaru tablicy, w której przechowywana była nazwa pliku. Odpowiedzi wskazały, że tablica powinna mieć rozmiar 16, aby pomieścić 15 znaków plus null-terminator. Użytkownik potwierdził, że po zwiększeniu rozmiaru tablicy problem został rozwiązany.
Wygenerowane przez model językowy.
REKLAMA