[Megoldva] Egész szám gyöke C-ben?

 ( pelz | 2008. november 28., péntek - 23:57 )

Sziasztok!

Ezzel a kóddal kínlódok:

#include math.h  // én vettem ki a kacsacsőröket!
#include stdio.h
#include stdlib.h
#include ctype.h

#define FALSE 0
#define TRUE  1

int foo(int szam) {
    int boolVal = FALSE;
    double a1, a2;

    a1 = szam;
    a2 = sqrt(a1);

    return boolVal;
}

int main() {

  return 0;
}

Hibának ezt írja:

Idézet:
CMakeFiles/p007_gyok.dir/main.o: In function `foo':
main.c:(.text+0x3a): undefined reference to `sqrt'

Ugyanakkor, ha a1 értékadásánál egy konstans értéket adok meg, lefordul a program hiba nélkül.

Pl.:

#include math.h
#include stdio.h
#include stdlib.h
#include ctype.h

#define FALSE 0
#define TRUE  1

int foo(int szam) {
    int boolVal = FALSE;
    double a1, a2;

    a1 = 4.345;
    a2 = sqrt(a1);

    return boolVal;
}

int main() {

  return 0;
}

Miért nem fordul le az első esetben? a1-et átkonvertálná egész típusúra? Nem az egésznek kellene double típusúvá konvertálódni?

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Így első ránézésre, hiányzik a fordítónak a -lm opció.
A tippem az, hogy második esetben, mint felesleges dolgot, ami úgysem hívódik meg, kioptimalizálja a fordító az sqrt-t, azért nem hiányzik linkelésnél.
A #define TRUE 1-el csak a gondok lesznek. Jobb választás a #define TRUE !FALSE

Érdekes jelenséget vettem észre. Ha úgy módosítom a másodikat, hogy az sqrt mindenképp lefusson (meghívom foo-t, és az sqrt után kiíratom az a2-t), és simán lefordítom, akkor a várakozásnak megfelelően nem talája az sqrt fv-t. De ha -O2-vel (-Os -O1 -O3 is) fordítom, akkor nem panaszkodik, lefordul, és helyesen működik. A -Ox paraméter megadásánál automatikusan linkeli a libm-et?

$ gcc --version
gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)

Nálam:

gcc --version
gcc (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu3)

Egyébként KDevelop-val fordítok, de most már kipróbálom manuálisan is!

A -Ox paraméter megadásánál automatikusan linkeli a libm-et?
Nem, de forditas kozben, mivel az a1=... ertekadas es az sqrt() kozott senki sem piszkalhat bele az a1 valtozo ertekebe, ki tudja szamolni maga a fordito is a gyokvonas eredmenyet. Kiszamitja, igy nem kell a libm-ben levo" sqrt()-t hasznalnia. Ha az a1, a2-t volatile-kent deklaralod, akkor mar -O* optimalizacional is kell a -lm, mert ekkor a fordito nem feltetelez(het)i hogy az a1=... es az sqrt() kozott valaki (egy masik sza'l, pl) nem buzeralja az a1 erteke't. Bar ez mondjuk nem is a peldabeli esetben lehet durva, mert egy belso automatikus valtozot mas szallal/processzel is modositani kicsit meredek. Hanem egy globalis valotozo eseten, ott ez elegge megszokott (mondjuk globalisokat hasznalni is kicsit meredek, de ez mas kerdes :)).

Értem, kösz. Nem gondoltam volna, hogy ilyesmit is kiszámolna fordításkor.

http://gcc.gnu.org/gcc-4.3/changes.html#mpfropts

Amint itt látható, az sqrt-t, és a cabs-t már régóta, az összes többit 4.3-tól tudja optimalizálni a gcc.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

+1

-lm opcióval nálam is jó a program.

Mi is ez a libm? A matematikai függvényeket tartalmazó könyvtár?

az.

Igen. olyasmi mintha a kódba beírnád hogy #INCLUDE math.h

hö?

ahogy te a c forrasba beirod, hogy "include math.h"
a -lm hasonlot ir be az elfbe.

- Use the Source Luke ! -

Ok, maradjunk annál, hogy tudom mi a -lm, de hagyjuk már ezt az inklúdos baromságot, mert semmi köze hozzá.
Az egyik precompile, a másik linkelés...

szerk. Csak azt akartam mondani, hogy érdemes lenne pontosan, és szakszerűen elmagyarázni a dolgokat.

A math.h-beli függvények a libm-re hivatkoznak, nem a libc-re, amit alapból linkel a linker.
Ez már csak ilyen link dolog, hogy külön linkelni kell.

--
"SzAM-7 -es, tudjátok amivel a Mirage-okat szokták lelőni" - Robi.