Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Kwalifikator typu restrict - jak działa?

23 Maj 2017 20:12 1185 29
  • Poziom 6  
    Witam.

    Próbuję dojść do tego jak działa powyższy kwalifikator.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Mam dwa pytania:
    Dlaczego mogę modyfikować obszar pamięci za pomocą *kopia = 10; skoro rest_tab powinno mieć ten obszar pamięci na wyłączność?

    static int * restrict rest_tab = (int*) malloc(10*sizeof(int));
    Kompilator zwraca błąd: initializer element is not constant
    Co ma do tego że wskaźnik zwracany przez malloc nie jest stały? Przecież użycie static w funkcji oznacza że zmienna pozostaje ciągle w "zasięgu", nie znika po wyjściu z funkcji, a nie że nie może zmieniać wartości.
  • Pomocny post
    Użytkownik usunął konto  
  • Poziom 6  
    A jak odniesiesz się do tego problemu ze wskaźnikiem static przy malloc()?
    W poniższy sposób działa. Czy slowo static użyte tak static int * restrict rest_tab = (int*) malloc(10*sizeof(int)); nabiera jakiegoś innego znaczenia?
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Użytkownik usunął konto  
  • Poziom 6  
    Ale to nie tyczy się tylko restrict, ale ogólnie.
    Kompilator mówi: initializer element is not constant
    Nie wiem co ma piernik do wiatraka. Static jest inicjalizowane podczas kompilacji i już, zmienna static bez łączności nie musi być stała.
  • Użytkownik usunął konto  
  • Użytkownik usunął konto  
  • Poziom 6  
    Racja, zgadzam się. Zmienna static bez łączności nie jest tworzona na stosie, żyje sobie od początku do końca programu, jedynie jej zasięg jest ograniczony do bloku lub funkcji, ale nadal nie rozumiem co powoduje że te zapisy są różne:

    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Poziom 20  
    Jakub17 napisał:
    Racja, zgadzam się. Zmienna static bez łączności nie jest tworzona na stosie, żyje sobie od początku do końca programu, jedynie jej zasięg jest ograniczony do bloku lub funkcji, ale nadal nie rozumiem co powoduje że te zapisy są różne:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Zastanów się kiedy te zmienne są tworzone i kiedy inicjowane.
  • Użytkownik usunął konto  
  • Poziom 6  
    Ok chyba już czaje. Czyli jeżeli zmienna jest klasy static (nie ważne o jakim zasięgu i łączoności - po prostu gdziekolwiek w programie) to zawsze musi być inicjalizowana wartością stałą a dopiero po tejże inicjalizacji może być dowolnie modyfikowana.

    Dodano po 2 [minuty]:

    rajszym napisał:

    Zastanów się kiedy te zmienne są tworzone i kiedy inicjowane.


    Wiem, że jest tworzona podczas startu programu. A inicjalizowana zaraz po jej stworzeniu?
  • Pomocny post
    Poziom 20  
    Jakub17 napisał:
    Racja, zgadzam się. Zmienna static bez łączności nie jest tworzona na stosie, żyje sobie od początku do końca programu, jedynie jej zasięg jest ograniczony do bloku lub funkcji, ale nadal nie rozumiem co powoduje że te zapisy są różne:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    W pierwszym przypadku jest najpierw (w czasie startu) inicjowana wartością zerową (NULL) a potem w funkcji (main) przypisywana jest do niej wartość zwracana przez malloc.
    W drugim przypadku musiałaby być od razu inicjowana wartością zwracaną przez malloc, dlatego wyrzuca błąd zgodnie z tym co wyżej napisał kol. Piotrus_999.
  • Użytkownik usunął konto  
  • Poziom 6  
    Czyli np. literał złożony też jest przechowywany w pamięci statycznej, no bo jest stałą:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    slowo1 i slowo2 jest w pamięci statycznej a tablica wskaźników jest tworzona w momencie napotkania zapisu (char*[]) {"slowo1","slowo2"} w kodzie programu i po jej stworzeniu jest inicjalizowana adresami tych literałów, które siedzą sobie w pamięci statycznej. Nazwa literału czyli: (char*[]) {"slowo1","slowo2"} jest adresem jej pierwszego elementu tablicy wskaźników a pierwszym elementem jest adres literału, stąd wskaźnik do wskaźnika wskin. Dobrze rozumiem? Tylko teraz nie wiem czy taka tablica wskaźników w może być statyczna czy automatyczna...
  • Użytkownik usunął konto  
  • Poziom 6  
    Powoduje mną czysta ciekawość, a zresztą uważam to za waźme informacje ktore słuzą zrozumieniu nie tylko tego konkretnego przykładu a szerszego zagadnienia pamięci. A co sie dzieje z tablicą wskaźników bedącą cześcią tego literału złożonego, gdzie te wskaźniki z tablicy są ulokowane w pamięci?

    Kod: c
    Zaloguj się, aby zobaczyć kod

    A w takim przypadku jak powyzej: Wiem ze literaly są kopiowane z pamięci statycznej do tablicy ale znowu nie wiem gdzie ta tablica jest umiejscowiona w pamięci... Czy zależy to wszystko od tego gdzie umieszczam literał złożony w kodzie? Wtedy tablice te mają rozny zasieg i czas zycia tzn. Albo automatyczny albo statyczny
  • Użytkownik usunął konto  
  • Użytkownik usunął konto  
  • Poziom 6  
    No tak, czyli wszystkie zmienne globalne i literały trafiają do pamięci statycznej niemodyfikowalnej w trakcie działania programu, natomiast zmienne automatyczne pojawiają się na stosie. I dane z pamięci statycznej mogą być tylko kopiowane (ich oryginał pozostaje niezmieniony) do zmiennych automatycznych, nie odwrotnie. Zgadza się?
  • Użytkownik usunął konto  
  • Poziom 6  
    Racja, trochę się zamotałem.
    Napisałem sobie poniżej prosty program i zastanawiam się czy nie jest on trochę niebezpieczny. Za pomocą malloc tworzę tablice wskaźników do tablic a następnie zapisuję pod tymi wskaźnikami jakieś łańcuchy. Tylko że teraz nie wiem czy te łańcuchy nie zniszczą jakiś innych danych, ponieważ nie rezerwowałem dla nich miejsca w pamięci. Łańcuchy są adresowane przez wskaźniki z tablicy, ale ich znaki nie wiadomo gdzie są przechowywane. Czym może znaki z bufora wejściowego przy pomocy gets() są umieszczane w pamięci statycznej jako zwykłe literały (czyli tak jak mówiłeś tylko do odczytu) a za pomocą tablicy wskaźników stworzonej przez malloc odwołuje się do tych literałów? Jak to jest?

    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Użytkownik usunął konto  
  • Poziom 6  
    Piotrus_999 napisał:
    ten malloc nie ma w ogóle sensu :)

    char (*temp)[dlugosc_s+1]; - juz alokuje na stosie odpowienia ilość pamięci :


    temp to wskaźnik do tablicy o rozmiarze x,tak? Zajmuje 4 bajty w pamięci (PC) jak zwykły wskaźnik, ale czy rezerwuje te x bajtow dla tej nie istniejącej tablicy? Przecież taki wskaźnik co najwyżej może wskazywać na taką tablice ale nie musi. Wskaźnik do całej tablicy to i tak wskaźnik do jej pierwszego elementu, czy się mylę?
  • Użytkownik usunął konto  
  • Poziom 6  
    Piotrus_999 napisał:

    char (*temp)[dlugosc_s+1]; - juz alokuje na stosie odpowienia ilość pamięci :


    Gdy mam zwykły wskaźnik np. int *wsk; to przecież nie oznacza że tworzy on miejsce w pamięci dla zmiennej int tylko dla jej adresu. Tak samo char(*temp)[10] tworzy miejsce w pamięci dla adresu tablicy. char(*temp)[10] to przecież taki sam obiekt jak np. double *wsk; z tym że pierwszy jest adresem do obiektu 10 bajtowego a drugi do 8 bajtowego. Dlatego nie rozumiem dlaczego napisałeś że deklaracja char (*temp)[dlugosc_s+1] już rezerwuje pamięć i malloc jest bez snesu, malloc() tworzy tablice niezainicjalizowanych wskaźników do obiektu np. char[10] ale nie rezerwuje pamięci dla tych obiektów.
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Więc gdy gets() umieszcza łańcuchy pod wskazanym adresem to nie wiem gdzie umieszczane są znaki tych łańcuchów... Dziwię się że to działa. Jak dla mnie powinna być jakaś tablica do ktorej gets() wgrywałby znaki łańcuchów a ew. później wskaźnik utworzony przez malloc() mógłby przyjąć adres łańcucha z tablicy.
    Np.
    Kod: c
    Zaloguj się, aby zobaczyć kod

    W powyższy kod bez tablicy temp nie działa i to rozumiem, wskaźniki z malloc() są pomocnicze do przechowania adresów łańcuchów z tablicy, ale łańcuch musi być najpierw umieszczony w pamięci(tablicy) by móc się do niego odwoływać za pomocą wskaźnika (z tablicy wskaźników). W powyższym kodzie tak samo powstała tablica wskaźników tylko że do wskaźników do char.
    Kurczę pogubiłem się już w tym wszystkim...
    Wychodzę z założenia że coś takiego:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Jest niemodyfikowalne, w sensie zawartości łańcucha, bo łańcuch jest w pamięci statycznej. Dlatego gdy gets() umieszcza łańcuch pod danym wskaźnikiem char (*temp)[10] to ten łańcuch nadpisuje aktualną zawartość pamięci niszcząc ją, ponieważ nie stworzyłem tablicy do przechowania tego łańcucha?

    Może to co piszę to jakiś bełkot, ale naprawdę pogubiłem się już w tym, wybacz.

    Dodano po 10 [minuty]:


    Intuicyjnie czuje ze moje rozumowanie jest bledne. Szukam tylko gdzie i dlaczego...
  • Użytkownik usunął konto  
  • Poziom 6  
    Piotrus_999 napisał:


    Jakub17 napisał:
    dy mam zwykły wskaźnik np. int *wsk; to przecież nie oznacza że tworzy on miejsce w pamięci dla zmiennej int tylko dla jej adresu. Tak samo char(*temp)[10] tworzy miejsce w pamięci dla adresu tablicy. char(*temp)[10] to przecież taki sam obiekt jak np. double
    Tak - nie wiem czy zauważyłeś że się poprawiłem - tak że nie cytuj nieporawnej wypowiedzi po raz n-ty. Mam ją skasowac, ale wtedy dyskusja traci sens jak nie wiadomo co to za cytaty.


    Wybacz, nie zrozumialem Twojej odpowiedzi, ze mowisz ze popelniles blad.
    Mowisz o czyms takim?
    https://www.visualstudio.com/pl/vs/cplusplus/?rr=https%3A%2F%2Fwww.google.pl%2F
  • Użytkownik usunął konto