Co je to nekompletní typ? (struktura) – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Co je to nekompletní typ? (struktura) – C / C++ – Fórum – Programujte.comCo je to nekompletní typ? (struktura) – C / C++ – Fórum – Programujte.com

 

oxidián0
Grafoman
16. 2. 2015   #1
-
0
-

Už asi pět dnů řeším chybovové hlášky ohledně incomplete type (struct). Chyby jsem už odstranil, ale nikdo mi nedokázal řádně vysvětlit: 1) co to vlastně je ten nekompletní typ (ohledně struktury) 2) jaké jsou jeho rozpoznávací znaky 3) čím se liší dvě struktury, které používám - proč u jedné musím při deklaraci objektu použít pointer a u druhého nemusím (když nepoužiju pointer tak to hodí chybu něco s neznámou velikostí u nekompletního typu).

Bod 3 je trochu více specifický a jde o to, že k funkcím na načtení obrázku (PNG, BMP) nebo pro zápis, potřebuju do funkce poslat objekt s informacemi (u PNG je to &data: jméno souboru, buffer, velikost souboru, kanály, atd. ; u BMP je to &bmpfile: tam posílám hlavně hlavičku, obsahující strukturu header a dib ). Obě struktury mají prakticky stejný tvar, obsahují podstruktury a členy typu char * nebo char **. Rozdíl je ale v tom, že u jedné při deklaraci objektu musím napsat ten pointer a bez toho to prostě nejde. A u té druhé (PNG_DATA data) si to klíďo píďo můžu napsat bez *. Na to mi nikdo nedokázal odpovědět. Takže jestli bude zájem tak sem pak pošlu ty typy abyste to mohli porovnat. Pod PNG_DATA jsem taky zkoušel dát ty samé structury co do BMPFILE a šlo to bez problému bez *.

Taky jsem nepochopil proč u BMP_FILE_struct musím použít deklaraci předem (forward) pomocí typedef:

struct BMP_FILE_struct; // forward declare
typedef struct BMP_FILE_struct BMPFILE;

struct BMP_FILE_struct {
  BMPHEADER header;
  BITMAPINFOHEADER dib;

}

a u toho PNG_DATA to mám zase jinak:

typedef struct PNG_DATA
{ ... }

Mohl by toto být zdoj toho rozdílného chování? Když tady odstraním typedef tak to zase bude hlásit někde jinde nějakou chybu ohledně "..." ale to teď kašlu - tuhle chybu řešit teď nechci. Ale asi kdybych ten tepedef odstranil, tak bych to musel deklarovat podobně jako PNG_DATA tedy pomocí forward deklarace a pak teprve psát struct? A ve výsledku bych dostal takový typ, že bych musel psát pointer PNG_DATA * data?.Případně naopak: kdybych ten BMP_FILE_struct napsal rovnou jako typedef, mohl bych to pak psát bez pointeru PNG_DATA?

Chci jen pochopit ty rozdíly a proč se to chová tak a tak. Asi nejsem jediný koho to dost mate, ale vidím, že to je zásadní k pochopení celé problematiky struktur a objektů.

Nahlásit jako SPAM
IP: 78.45.199.–
KIIV
~ Moderátor
+43
God of flame
16. 2. 2015   #2
-
0
-

Kdyz vytvaris objekt ci strukturu, tak prekladac musi znat kompletni deklaraci typu prave kvuli te vysledne velikosti vysledku. Tusim, ze to neni potreba u reference a pointeru, protoze u toho velikost zna (coz je v obou pripadech velikost pointeru). Hlavne pro cyklicke zavislosti jsou nekompletni typy dulezite - idealni je to pro rozdelenou implementaci - kdy header nemusi vedet nic o pouzite tride, ale v implementaci uz to neni problem naincludovat.

Typedef taky nemuze udelat alias k necemu, co neexistuje, ale potrebuje akorat vedet, ze to je treba struktura.

Kazdopadne bez ukazek jak co vypada a co to hlasi se blbe odhaduje, co tam delas blbe.

Nahlásit jako SPAM
IP: 94.113.95.–
Program vždy dělá to co naprogramujete, ne to co chcete...
oxidián0
Grafoman
16. 2. 2015   #3
-
0
-

Teď už tam chyby nejsou, ale zajímá mě ten rozdíl mezi těmi dvěma typy struktur. Těch souborů je ale hodně. Byl by si ochoten se na to podívat, kdybych ti celý projekt poslal zabalený? Asi nemá smysl tu posílat odkazy na main.c, data_types.h, bmpfile_types.h, bmpfile.h, bmpfile.c, nebo mám poslat odkaz jen na data_types.h

http://paste.ofcode.org/dZ74UDW4ctzbBX9EbJETzB

a bmpfile.h

http://paste.ofcode.org/spQ87uZi7bdDRCmnbEam3k

? Tam jsou ty struktury.

Pozn. s JPEG_DATA jsem taky neměl žádný problém. Takže mě zajímá co musím udělat abych BMP_FILE_struct mohl používat stejně jako ty dva výše. Ale možná to nejde kvůli těm zpětným referencím jak říkáš. libjpeg a libpng jsou knihovny a jako takové jsou uloženy jinde takže už jsou nakompilovány a comilátor tedy nemůže vidět ty zacyklení

Nahlásit jako SPAM
IP: 78.45.199.–
KIIV
~ Moderátor
+43
God of flame
17. 2. 2015   #4
-
0
-

Kazdopadne tam asi zadnou zaludnost nevidim...

typedef struct neco  neco_jineho   je akorat alias abys v C nemusel vsude psat:

struct neco   promenna;

Ale v C++ je to vcelku zbytecne. To same to  typedef struct BMP_FILE_struct BMPFILE pred samotnou definici. Klidne se to mohlo presunout za a usetrila by se asi ta forward deklarace.

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
oxidián0
Grafoman
17. 2. 2015   #5
-
0
-

Proč toto dává chybu?

line 25|multiple definition of `createTest'
line 25|first defined here

typedef struct STest {
    int v;
    char *str;
}Test;
 
// #25
Test *createTest(int v,char *str) {
    Test *t=(Test*)malloc(sizeof(Test));
    t->v=v;
    t->str=str;
    return t;
}
Nahlásit jako SPAM
IP: 78.45.199.–
KIIV
~ Moderátor
+43
God of flame
17. 2. 2015   #6
-
0
-

To se ti snazi vysvetlit tou chybovou hlaskou:

multiple definition of `createTest'

A znamena to v prekladu vicenasobna definice funkce createTest

Coz znamena, ze je tam vickrat stejne pojmenovana funkce i s tim co ma provadet (deklarace je jen jake parametry ceka a co vraci, definice je i co ma delat).

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
oxidián0
Grafoman
17. 2. 2015   #7
-
0
-

To jsem pochopil že tam údajně má být ta funkce víckrát, ale ona tam je fakticky jenom jednou. KLidně ji mohu přejmenovat a bude to psát tu stejnou chybu.

Edit:

Přesunul jsem to z hlavičky do .c a už to nedělá

Nahlásit jako SPAM
IP: 78.45.199.–
KIIV
~ Moderátor
+43
God of flame
17. 2. 2015   #8
-
0
-
Nerozhodně

Ano, do headeru se davaji jen deklarace, protoze jakmile includujes v projektu header file s definici funkce vickrat, tak mas tu funkci v kazdem objektovem souboru a linker nevi, kterou z nich ma pouzit.

Kazdopadne bys mel asi zacit studovat zaklady C/C++ jako jak funguje kompilace a tak

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
oxidián0
Grafoman
17. 2. 2015   #9
-
0
-

Je to zkušební kód ale zase nefunguje. Dal jsem ho do souboru, který v main.c includuju z jiného .c

A v main() to mám toto:

Test *t=createTest(100,"fart"); // #43
    printf("%i,%s\n",t->v,t->str);
    free(t);


Chyby:

43|error: unknown type name 'Test'|

44|error: request for member 'v' in something not a structure or union

Nahlásit jako SPAM
IP: 78.45.199.–
KIIV
~ Moderátor
+43
God of flame
17. 2. 2015   #10
-
0
-

.c soubory se neincluduji.. Prekladaji se samostatne a pak se to cele slinkuje. (opet zaklady)

Chyba znamena, ze nemas nejaky include, kde je ten Test deklarovan/definovan

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
oxidián0
Grafoman
17. 2. 2015   #11
-
0
-

Tak jsem se špatně vyjádřil. Includuju hlavičku, ale přesunul jsem tu definici do souboru .c.

Tak když to teď deklaruju

typedef struct STest Test;

tak už mi to tu chybu nepíše, ale zase píše:

main.c|44|error: dereferencing pointer to incomplete type

A jsem tam kde sem byl na začátku

Nahlásit jako SPAM
IP: 78.45.199.–
KIIV
~ Moderátor
+43
God of flame
17. 2. 2015   #12
-
0
-

k dereferenci uz musi mit k dispozici kompletni strukturu Test - nestaci jen ta neuplna - uz proste musi vedet, jestli to jde, nebo ne.

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
oxidián0
Grafoman
17. 2. 2015   #13
-
0
-

Čemu říkáš kompletní struktura? V #5 je struktura definovaná, není snad kompletní?

Nahlásit jako SPAM
IP: 78.45.199.–
oxidián0
Grafoman
17. 2. 2015   #14
-
0
-

Konečně vyřešeno.

Takže celý problém byl v tom, že:

1) definice té struktury měla být v headeru, nikoliv v souboru c.

2) v souboru c bylo třeba includovat ten header s definicí

test.h

typedef struct STest {
    int v;
    char *str;
} Test;

Chyba které jsem se doupouštěl:

test.c

#include "test.c"

Chyba které jsem se dopouštěl:

test.h

typedef struct STest Test;


(popřípadě žádná deklarace)

test.c

typedef struct STest {
    int v;
    char *str;
} Test;

Test *createTest(int v,char *str){...} 
// compiler hledá definici typu Test a nemůže ji najít. 
// Vidí pouze deklaraci

Compiler se dívá do headeru a nevidí deklaraci. To znamená, že když má kompilovat v souboru .c funkci, která používá typ, který nebyl v headeru definován tak ho nezná. Já se však domníval, že je ten typ definovaný právě před tou funkcí v souboru .c.

Nahlásit jako SPAM
IP: 78.45.199.–
oxidián0
Grafoman
17. 2. 2015   #15
-
0
-

Tys mě docela zmátl s tím tvrzením, že do headeru se dávají jen deklarace. To se pak není divit tomu že jsem to nemohl týden pochopit když to nikdo nedokázal jednoduše a srozumitelně vysvětlit. Asi taky nechápeš, že mě jen nějaké studování z knih či manuálů nestačí, to si mohu přečíst obecné poučky kdekoliv ale ty mi nic neříkaj.

Nahlásit jako SPAM
IP: 78.45.199.–
KIIV
~ Moderátor
+43
God of flame
17. 2. 2015   #16
-
0
-

#15 oxidián
ta "jen deklarace" patrila jen k funkcim :)

Tridy jsou na tom trochu jinak - u nich se mluvi o forward deklaraci (class X;), deklaraci (kde vetsinou nejsou implementace metod, ale uz je prekladaci jasne rozhrani, velikost a tak), a implementace jednotlivych metod)

Nahlásit jako SPAM
IP: 94.113.95.–
Program vždy dělá to co naprogramujete, ne to co chcete...
oxidián0
Grafoman
17. 2. 2015   #17
-
0
-

A teď asi mluvíš o C++. Ale já pracuji s C.

Nahlásit jako SPAM
IP: 78.45.199.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 2 hosté

Podobná vlákna

štruktúra — založil street punk

Struktura — založil sexmachina

Struktura tabulky — založil Jirka

Struktura s pomoci new — založil Hlavinka

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý