Może zacznę od wypisania błędów w Twoim kodzie a potem odpowiem na pytania.
Używanie zmiennych globalnych to zła praktyka, nie jest to błąd, ale lepiej tak nie robić.
struct element nie jest poprawnym elementem stosu, w tej wersji to nie ma prawa działać. Stos w postaci listy (bo taki zacząłeś pisać) składa się z elementów, które mają jakąś wartość i wskaźnik na kolejny/poprzedni element w liście. Twój element ma wartość i wskaźnik na inta, a nie na kolejny/poprzedni element listy czyli struct element * poprzednik. Mam nadzieję, że Cię tym nie zaskoczę, ale typy mają znaczenie :P
struct element {
int wartosc;
int *poprzednik;
};
To nie jest deklaracja zmiennej. To jest definicja typu. Niżej w kodzie nie ma sensu coś takiego:
struct element {
int wartosc;
int *poprzednik;
}elem = { *(&wartosc), NULL };
wystarczy:
struct element elem = {wartosc,NULL};
Bo typ struct element jest już zdefiniowany. Po drugie: linijke niżej robisz tak:
elem.poprzednik = top;
po co wstawiłeś tam NULLa linijkę wyżej, jeśli zaraz go nadpisujesz. Zrób tak:
elem = { wartosc, top };
Jak już jesteśmy tutaj to:
*(&wartosc)
yyy? Czemu, dlaczego, po co? Pobierasz adres zmiennej wartość, a potem go dereferenciujesz tzn wyciągasz wartość tego co się w tej pamięci kryje, czyli: wartosc == *(&wartosc). * i & się tutaj znoszą.
top = &elem;
Typ elem to struct element a top to int*. Lepiej nie przypisywać niekompatybilnych wskaźników. Czasem działa, czasem nie, bo nigdzie w standardzie nie ma, że wszystkie wskaźniki będą miały tą samą wielkość. Nie mówiąc już o tym, że strasznie to zaciemnia kod i generuje ostrzeżenia :P
void pop(){
int tmp;
tmp = *top;
top=elem.poprzednik;
elem.wartosc=tmp
}
elem był lokalną zmienną w innej funkcji. Nie jest tu widoczny.
int *element;
element = (int*)malloc(sizeof(struct element));
struct element {
int wartosc;
int *poprzednik;
}elem = { *(&wartosc), NULL };
malloc w ten sposób jest bez sensu. Po pierwsze totalnie niekompatybilne typy. Wielkość struct element to 2x wielkość inta. Po drugie alokujesz dynamicznie składową elementu, a sam element jest niszczony po wyjściu z funkcji.
Wykładowca wymaga używania funkcji malloc i free oraz wskaźników
Bardzo dobrze, że wymaga bo inaczej się tego nie da napisać.
Może kilka zdań o dynamicznej alokacji. Zmienne lokalne są automatycznie zwalniane na końcu zakresu. Tzn, że tworzony przez Ciebie struct element elem. Znika po wyjściu z funkcji. Mówimy o takiej syutacji:
int* fun() {
int x = 5;
int * wsk = &x;
return wsk;
}
int main() {
int * result = fun();
printf("%d", result);
}
Powinno wypisać jakieś śmieci. Bo int x na który wskazuje result został zniszczony po wyjściu z funkcji. Zapobiec temu można dynamiczną alokacją (malloc, free), która pozwala nam samym decydować kiedy pamięć jest zwlaniana:
int* fun() {
int * x = malloc(sizeof(int));
*x = 5;
return x;
}
int main() {
int * result = fun();
printf("%d\n", *result);
free(result);
printf("%d\n", *result);
}
Teraz pierwszy printf wypisze nasza 5. A drugi śmieci bo zdecydowaliśmy się zwolnić pamięć i jest ten sam efekt co wcześniej po wyjściu z funkcji. Jednak w przeciwieństwie do 1. przykładu tutaj to my decydujemy kiedy pamięć jest zwalniana. W 1. przypadku kompilator sam automatycznie zwalniał pamięć po wyjściu z zakresu.
Szczerze odpowiedz na pytania nie ma sensu przed naprawieniem tych błędów, bo teraz ten program nie ma za bardzo sensu.
A tak na marginesie - Twój problem prawie wcale nie różni się tak bardzo od innych list na tym forum. Poczytaj jak oni to robili, bo nie chce mi się tego samego pisać setny raz.