Błędy LNK2019 i LNK1120 w funkcji swap()

Błędy LNK2019 i LNK1120 w funkcji swap()
Hesoyam
  • Rejestracja:ponad 4 lata
  • Ostatnio:6 miesięcy
  • Postów:32
1

Witam mam mały problem

Kopiuj
#include <stdio.h>  //błąd (na dole) LNK2019 i LNK1120
#include <stdlib.h>

void swap(int, int);

int main(void)
{
	printf("%s\n", "Witaj swiecie!");
	
	int a = 21;
	int b = 17;

	swap(a, b);
	printf("main: a = %d, b = %d\n", a, b);
	
	
	return EXIT_SUCCESS;

Dwa błedy:

  1. LNK2019 nierozpoznany symbol zewnętrzny swap przywołany w funkcji main. WIERSZ 1
  2. LNK1120 liczba nierozpoznanych elementów zewnętrznych: 1 WIERSZ 1
edytowany 3x, ostatnio: Riddle
Riddle
@Hesoyam: Fajnie że napisałeś post na forum! Następnym razem postaraj się dodać oznacznik ```c++, by włączyć kolorowanie składni języka programowania.
Iroh
  • Rejestracja:11 miesięcy
  • Ostatnio:2 miesiące
  • Postów:7
4

Masz zadeklarowaną funkcję swap, ale nie masz jej definicji, czyli ciała z kodem.

Linker próbuje znaleźć miejsce w kodzie z ktorym może połączyć Twoje wywołanie funkcji, ale takiego nie widzi, więc dostajesz błąd o nierozponanym symbolu zewnętrznym.

Hesoyam
  • Rejestracja:ponad 4 lata
  • Ostatnio:6 miesięcy
  • Postów:32
1

Dziękuję za szybką odpowiedź teraz rozumiem :-)

Manna5
  • Rejestracja:około 6 lat
  • Ostatnio:około godziny
  • Lokalizacja:Kraków
  • Postów:641
5

Poprawiony kod, jeśli dobrze rozumiem o co ci chodziło:

Kopiuj
#include <stdio.h>
#include <stdlib.h>

void swap(int *, int *);

int main(void)
{
	printf("%s\n", "Witaj swiecie!");
	
	int a = 21;
	int b = 17;

	swap(&a, &b);
	printf("main: a = %d, b = %d\n", a, b);
	
	
	return EXIT_SUCCESS;
}

void swap (int *ap, int *bp)
{
	int temp;

	temp = *ap;
	*ap = *bp;
	*bp = temp;
}

Problemem był nie tylko brak funkcji swap, ale też brak nawiasu klamrowego kończącego funkcję main oraz to, że jeżeli (jak się domyślam) funkcja swap miała zamieniać wartości dwóch zmiennych, to nie dasz rady tego zrobić przekazując do funkcji tylko wartości tych zmiennych - musisz w tym celu przekazywać je przez wskaźnik jak w poprawionym kodzie.


edytowany 1x, ostatnio: Manna5
KS
  • Rejestracja:prawie 4 lata
  • Ostatnio:27 minut
  • Postów:623
0

Kolego EXIT_SUCCESS i EXIT_FAILURE przekazujesz tylko do exit.
Na końcu funkcji jak sukces to dajesz

return 0;

Na upartego, ale w Twoim wypadku to nie ma sensu:
exit( EXIT_SUCCESS );

exit robi pewne rzeczy w tle, W razie czego zaglądaj do manualu.

KS
Poniżej o Tym wspomniałem. Ale fajnie, że dałeś źródło
Manna5
  • Rejestracja:około 6 lat
  • Ostatnio:około godziny
  • Lokalizacja:Kraków
  • Postów:641
0

Funkcja exit jest równoważna ze zwróceniem wartości z main.


Manna5
Jeśli chodzi ci o rzeczy typu automatyczne zamknięcie plików i wywołanie funkcji określonych przez atexit to wyjście z main też to robi.
KS
  • Rejestracja:prawie 4 lata
  • Ostatnio:27 minut
  • Postów:623
1

Nie jest, potem rozwinę.

Hesoyam
  • Rejestracja:ponad 4 lata
  • Ostatnio:6 miesięcy
  • Postów:32
0

Kiedy używać wskaźników a kiedy zwykłych zmiennych?🤔

KS
  • Rejestracja:prawie 4 lata
  • Ostatnio:27 minut
  • Postów:623
1

Proszę bardzo

Kopiuj


#include <stdio.h>

int main( int argc, char *argv[])
{
    
    if( argc > 1 )  {
        
        return 5;
        
    }
    
    if( main( 2, (char *[] ){ "one", "two" } ) == 5 )
      printf( "widzimy roznice ?" );
    
    return 0;
    
}

Kopiuj

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


int main( int argc, char *argv[])
{
    
    if( argc > 1 )  {
        
        exit( 5 );
        
    }
    
    if( main( 2, (char *[] ){ "one", "two" } ) == 5 )
      printf( "widzimy roznice ?" );
    
    return 0;
    
}

Wiem, że to brudny hack ale to moja dzika karta w tym momencie aby naprostować kogoś, że takie g**no w kodzie jak exit(0); ma się nie pojawiać.

Nie wspomnę o tym, że EXIT_SUCCESS i EXIT_FAILURE są dosyć mgliście zdefiniowane, pod windą oczywiście potrafią zwracać nieintuicyjne wartości.
Więc radosne return EXIT_SUCCESS które nie zwraca zera i wysadzi Ci skrypt w shellu pod cygwinem to ostatnia rzecz na jaką masz ochotę.

No i tego ten return to statement a exit to funkcja. Jednak dla mnie trochę inne rzeczy.

edytowany 1x, ostatnio: ksh
Zobacz pozostałe 25 komentarzy
KS
Ziomuś to ty wparowałeś mi pod mojego posta wywijając pięścią, że wypisuje bzdury a teraz chcesz z podkulonym ogonem się wykręcić jakobyś to był Ty ofiarą
KS
Każdy kto przeanalizuje kod w moim poście zrozumie o co mi chodziło. + na dobitkę sam wkleiłeś cytat ze standardu potwierdzający co napisałem.
KS
A najżałośniejsze jest to, że sugerujesz, że mącę początkującym, za to poklepywanie idioty który będzie pisał na końcu maina exit( 0 ) jest już spoko.
AO
@ksh: z exit(0) nie ma nic złego bo to ten sam efekt co return 0. A jak będziesz cały czas się tak zachowywał to znowu mod przyjdzie i usunie twoje posty.
KS
Nie jest to ten sam efekt, co potwierdza standard ,który tu wkleiłeś.
Marius.Maximus
  • Rejestracja:ponad 14 lat
  • Ostatnio:około 2 godziny
  • Postów:2104
1
Hesoyam napisał(a):

Kiedy używać wskaźników a kiedy zwykłych zmiennych?🤔

Nie ma wskaźnika bez "zwykłych zmiennych" ;)
Chyba że wskaźnik do wskaźnika , ale finalnie i tak musi być gdzieś na końcu jakaś jakaś "zwykła zmienna"


--
Nie przyjmuję reklamacji za moje rady, używasz na własną odpowiedzialność.
Programowanie bez formatowania to jak chodzenie ze spodniami spuszczonymi na kostki. Owszem da się ale po pierwsze nie wygodne, po drugie nieprzyzwoicie wygląda.
Przed zaczęciem nowego wątku przeczytam problem XY
kaczus
  • Rejestracja:około 10 lat
  • Ostatnio:około 4 godziny
  • Lokalizacja:Łódź
  • Postów:1402
0
Hesoyam napisał(a):

Kiedy używać wskaźników a kiedy zwykłych zmiennych?

zawsze używasz zmiennych (albo stałych), wskaźnik zaś wskazuje miejsce do nich. Wskaźnika (oczywiście to uproszczenie, ale dla pytania wystarczające) używamy tam, gdzie chcemy przekazać dostęp do zmiennej zdefiniowanej w innym miejscu. Tu masz zmienna zdefiniowaną w funkcji main, ale chcesz wartość tej zmiennej zmienić w funkcji swap, dlatego przekazujesz jej wskaźnik na tą zmienną.


Ogólnie na prace domowe mam stawki zaporowe. Czasem coś o programowaniu znajdzie się na mojej stronie
MY
  • Rejestracja:prawie 10 lat
  • Ostatnio:2 dni
  • Postów:1083
1
Hesoyam napisał(a):

Kiedy używać wskaźników a kiedy zwykłych zmiennych?🤔

Można powiedzieć, że używasz "zwykłej zmiennej" jeśli interesuje Cię po prostu wartość danej zmiennej i nic więcej. Klasycznie to będzie coś w stylu:

Kopiuj
int sum(int a, int b)
{
  return a + b;
}

Tutaj mamy przekazać do funkcji wartości i zwrócić ich sumę. Jednak jeśli przekazujemy jakiś duży obiekt, np dużego stringa/obszar pamięci i chcemy mu policzyć sumę kontrolną (a może to mieć np. 10MB) więc unikamy kopiowania danych i wtedy przekazujemy do funkcji wskaźnik:

Kopiuj
int getCRC(char *buff, int size)
{
  .... // przelecenie sie po calej pamieci i policznie sumy kontrolnej
  return crc;
}

Bo trzeba wiedzieć, że wywołując funkcję i przekazując do niej jakiś parametr tworzona jest nowa zmienna lokalna w funkcji na podstawie źródłowej. Nic nie stoi na przeszkodzie przekazać wartość buff przez wartość, ale co jeśli będzie on miał rozmiar 1GB? Wtedy będzie trzeba całość skopiować do zmiennej lokalnej, co zajmie czas, może nie starczyć miejsca na stosie itp. Dlatego aby uniknąć zbędnego kopiowania przekazujemy adres bufora z rozmiarem i już ;) O ile w przypadku pierwszej sytuacji skopiowanie dwóch zmiennych typu int będzie szybkie i bez znaczenia, to już kopiowanie całego bufora który ma potencjalnie nie wiadomo ile GB jest bez sensu.

Z tego co wyżej napisałem wynika coś ciekawego. Funkcja działa na swoich lokalnych kopiach, więc taka funkcja:

Kopiuj
void swap(int a, int b)
{
  int temp;
  temp = a;
  a = b;
  b = temp;
}

zamieni swoje lokalne zmienne, więc jeśli damy:

Kopiuj
void swap(int a, int b);

int x = 123;
int y = 666;
swap(x,y);
printf (x=%d, y=%d, x, y);

wypisze, że dalej x=123, y=666
Przekazanie wskaźników do zmiennych x oraz y pozwoli na zamianę już zmiennych np z funkcji wywołującej:

Kopiuj
void swap(int *a, int *b);

int x = 123;
int y = 666;
swap(&x,&y);
printf (x=%d, y=%d, x, y);

w tym przypadku już poprawnie będzie wypisane x=666, y=123
Zwróć uwagę na zapis swap(&x,&y); z wykorzystaniem operatora pobrania adresu zmiennej & w wywołaniu funkcji swap

Przy okazji, kod pisany z palca, bez sprawdzenia w IDE, więc mogą być literówki ;)

Manna5
  • Rejestracja:około 6 lat
  • Ostatnio:około godziny
  • Lokalizacja:Kraków
  • Postów:641
0
ksh napisał(a):

Proszę bardzo

Kopiuj


#include <stdio.h>

int main( int argc, char *argv[])
{
    
    if( argc > 1 )  {
        
        return 5;
        
    }
    
    if( main( 2, (char *[] ){ "one", "two" } ) == 5 )
      printf( "widzimy roznice ?" );
    
    return 0;
    
}

Takie coś jak (char *[] ){ "one", "two" } to jest chyba C++, i o ile nie ma to bezpośrednio znaczenia w temacie różnicy pomiędzy exit a return z main, bo można przepisać przykład bez tej składni, to ogólnie w standardzie C++ mogą być jakieś inne zasady niż w ANSI C.

ksh napisał(a):
Kopiuj

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


int main( int argc, char *argv[])
{
    
    if( argc > 1 )  {
        
        exit( 5 );
        
    }
    
    if( main( 2, (char *[] ){ "one", "two" } ) == 5 )
      printf( "widzimy roznice ?" );
    
    return 0;
    
}

Wiem, że to brudny hack ale to moja dzika karta w tym momencie aby naprostować kogoś, że takie g**no w kodzie jak exit(0); ma się nie pojawiać.

Wywoływanie main (gdy jest funkcją główną w środowisku hostowanym) może stanowić UB, a więc w normalnym kodzie nie występuje, toteż argument ten nie ma sensu.

Natomiast jeśli chodzi Ci o to, że zakańczanie całego programu gdzieś w jakiejś funkcji poza main (co umożliwia exit) jest złe pod względem stylu programowania, to się zgadzam. Poza jakimiś krytycznymi błędami, ale wtedy jest abort. Niemniej jednak nie widzę nic złego w użyciu exit zamiast return pod warunkiem że i tak ma to miejsce wewnątrz main.

ksh napisał(a):

Nie wspomnę o tym, że EXIT_SUCCESS i EXIT_FAILURE są dosyć mgliście zdefiniowane, pod windą oczywiście potrafią zwracać nieintuicyjne wartości.
Więc radosne return EXIT_SUCCESS które nie zwraca zera i wysadzi Ci skrypt w shellu pod cygwinem to ostatnia rzecz na jaką masz ochotę.

Tak to jest z C, że czasami nie wszystkiego możesz być pewien, zwłaszcza w nietypowych sytuacjach typu Cygwin. W środowisku w 100% linuxowym EXIT_SUCCESS przy normalnym kompilatorze powinno jednak zawsze wynosić 0, bo tak to działa na tym systemie, choćby właśnie jeśli chodzi o skrypty.

ksh napisał(a):

No i tego ten return to statement a exit to funkcja. Jednak dla mnie trochę inne rzeczy.

OK i może nawet ma to znaczenie praktyczne, bo np. x || exit (1); ale nie x || return 1;, ale mi chodziło o różnicę w działaniu czyli tym co się stanie gdy już w jakiś sposób dojdzie do wywołania exit / powrotu z main.

Jeśli ktoś jest ciekawy, była podobna dyskusja na StackOverflow: https://stackoverflow.com/questions/35471878/difference-between-exit-and-return-in-main-function-in-c


KS
  • Rejestracja:prawie 4 lata
  • Ostatnio:27 minut
  • Postów:623
0

"Takie coś jak (char *[] ){ "one", "two" } to jest chyba C++, i"

Takie coś to jest C kolego a nie C++. Ja C++ nie używam.

Jedyny błąd jaki tam zrobiłem, to że std wymaga NULL na końcu argv.

"Wywoływanie main (gdy jest funkcją główną w środowisku hostowanym) może stanowić UB, a więc w normalnym kodzie nie występuje, toteż argument ten nie ma sensu."

Z jakiej paki te rewelacje? To jest nie prawda.

edytowany 1x, ostatnio: ksh
Manna5
  • Rejestracja:około 6 lat
  • Ostatnio:około godziny
  • Lokalizacja:Kraków
  • Postów:641
0

XD okazuje się że GCC to kompiluje. Ale to może C99 czy jakieś rozszerzenie, bo przed chwilą przejrzałem gramatykę i nie ma czegoś takiego w wyrażeniu.


KS
  • Rejestracja:prawie 4 lata
  • Ostatnio:27 minut
  • Postów:623
0

Tkz czego niby nie ma? Tam nie ma nic nadzwyczajnego.

Manna5
  • Rejestracja:około 6 lat
  • Ostatnio:około godziny
  • Lokalizacja:Kraków
  • Postów:641
0

Nie ma takiej składni że masz inicjator tablicy wewnątrz wyrażenia.


MarekR22
Moderator C/C++
  • Rejestracja:ponad 17 lat
  • Ostatnio:8 minut
2

Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
Manna5
  • Rejestracja:około 6 lat
  • Ostatnio:około godziny
  • Lokalizacja:Kraków
  • Postów:641
0

"since C99". Właśnie. Pisałem że to może być C99.


edytowany 1x, ostatnio: Manna5
MarekR22
chyba się nie zrozumieliśmy. Gadanie "nie ma takiej składni, chyba że od C99", nie jest zbyt jasne. Dlatego znalazłem jak nazywa się ten feature i dałem do niego linka, żeby było wszystko jasno i profesjonalnie wyjaśnione. Najlepsze odpowiedzi to takie, które są udokumentowane.
KS
  • Rejestracja:prawie 4 lata
  • Ostatnio:27 minut
  • Postów:623
0

Tylko od 25 lat w standardzie. < face palm >

MarekR22
Moderator C/C++
  • Rejestracja:ponad 17 lat
  • Ostatnio:8 minut
0
ksh napisał(a):

Tylko od 25 lat w standardzie. < face palm >

Pretensje zgłaszaj do Microsoft.
MSVC nie wspiera w pełni wymaganych funkcji C99 i pewnie dlatego nie istnieje dla Manna5
/std (Specify Language Standard Version) | Microsoft Learn

The compiler doesn't implement several required features of C99, so it isn't possible to specify C99 conformance, either.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
KS
Nikt go siłą nie trzyma na tym windowsiku. ;-)
kaczus
  • Rejestracja:około 10 lat
  • Ostatnio:około 4 godziny
  • Lokalizacja:Łódź
  • Postów:1402
0
ksh napisał(a):

Tylko od 25 lat w standardzie. < face palm >

W standardzie języka C, a nie C++.


Ogólnie na prace domowe mam stawki zaporowe. Czasem coś o programowaniu znajdzie się na mojej stronie
KS
Przecież wątek jest o C, C++ nas nie obchodzi.
kaczus
fakt, mój błąd, ktoś w wątku włączył też rozmowę na temat C++ i tryb mi sie przełączył.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.