Chyba – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Chyba – C / C++ – Fórum – Programujte.comChyba – C / C++ – Fórum – Programujte.com

 

oxidián0
Grafoman
5. 4. 2015   #1
-
0
-

Nedaří se mi vyřešit tento problém:

http://paste.ofcode.org/LsS3pkYmcsmeBrEYPZKG36

alokace paměti, řádek 102 vrací chybu

incompatible types when assigning to type 'TASK_REQUEST_t' from type 'void *'|

TASK_REQUEST_t je zatím prázdná struktura.

w->task.requests[request_no] = malloc( sizeof(TASK_REQUEST_t) );
typedef struct TASK_FILE_
{
    TASK_REQUEST_t * requests;
} TASK_FILE_t;

Co dělám špatně?

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

C++?

Proste to pretypuj

Nahlásit jako SPAM
IP: 93.91.152.–
Program vždy dělá to co naprogramujete, ne to co chcete...
ingiraxo+15
Grafoman
5. 4. 2015   #3
-
0
-

jinak když alokuješ pole ukazatelů (řádek 48), tak by si neměl používat sizeof(int), protože na x64 ti to padne, protože tam velikost ptr není 4byte, ale 8byte.. ciže ideálně použít sizeof na ptr toho objektu, kterej bude v poli, nebo ptr na int, ale doporučuju na objekt, je to potom přehlednější 

sizeof(TASK_REQUEST_t *)

K té chybě ti to už napsal KIIV, inspiruj se řádkem 48 ;)

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
PiranhaGreg0
Stálý člen
5. 4. 2015   #4
-
0
-

Pokud kód kompiluješ jako C++, nevidím důvod proč nepoužívat new, tedy

w->task.requests[request_no] = new TASK_REQUEST_t;

Je to míň náchylný na chybu a vyhneš se přetypování.

Nahlásit jako SPAM
IP: 109.81.210.–
ingiraxo+15
Grafoman
5. 4. 2015   #5
-
0
-

#4 PiranhaGreg
používá C++, ale vypadá, že má rád C-like alokaci

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
PiranhaGreg0
Stálý člen
5. 4. 2015   #6
-
0
-

Mě se právě tento přístup moc nelíbí. Buď píšu v Cčku a využívám kompilátor pro C a nebo píšu v C++ se vším všudy a používám kompilátor pro C++. Tento mix podle mě nevede k ničemu dobrému...

Nahlásit jako SPAM
IP: 109.81.210.–
oxidián0
Grafoman
5. 4. 2015   #7
-
0
-

#2 KIIV
C. To jsem už zkoušel přetypovat a chyba stále. A proč to přetypovat to by mělo jít i bez toho, aby člověk mohl ověřit platnost pointeru.

Nahlásit jako SPAM
IP: 78.45.199.–
oxidián0
Grafoman
5. 4. 2015   #8
-
0
-

#5 ingiraxo
Nepamatuji si kdy jsem naposledy použil C++. Naposledy co si pamatuji jsem přepisoval funkci z C++ do C.

Nahlásit jako SPAM
IP: 78.45.199.–
PiranhaGreg0
Stálý člen
5. 4. 2015   #9
-
0
-
Nahlásit jako SPAM
IP: 109.81.210.–
oxidián0
Grafoman
5. 4. 2015   #10
-
0
-

Ještě jednou moje hláška:

Incompatible types when assigning to type 'TASK_REQUEST_t' from type 'void *'

Malloc vrací pointer, ale podle té hlášky .requests[request_no] je struktura, tak co s tím? .requests[request_no] má být pointer na strukturu.

Paměť na w->task.requests jsem alokoval takto:

w->task.requests = (TASK_REQUEST_t *) malloc (w->task.pointers_count * sizeof(int) );

Takže to má být pole pointerů. Takže nechápu tu hlášku, Proč tam je assigning to type 'TASK_REQUEST_t' ?

Tohle musí být nějaká banalita, dyď jsem to už tolikrát dělal tak co nevidím?

#10 PiranhaGreg
To je něco jiného, chceš alokovat paměť pro pointer, ale pointer nemá velikost 1 byte.

Nahlásit jako SPAM
IP: 78.45.199.–
ingiraxo+15
Grafoman
5. 4. 2015   #11
-
0
-

#8 oxidián
protypování je nutný, malloc a calloc ti jen alokujou místo na heapu o nějaký velikosti a vrátí ti ukazatel na adresu což je void* a ten logicky musíš přetypovat na tvůj ptr na struktůru

pokud ten "requests" je klasický pole, tak to takto alokovat nemůžeš, udělej z toho pole ukazatelů na struktůru 

// alokace pole třech ukazatelu na strukturu
TASK_REQUEST_t** requests = (TASK_REQUEST_t **) malloc(3 * sizeof(TASK_REQUEST_t *));
// alokace struktury
requests[0] = (TASK_REQUEST_t *) malloc(sizeof(TASK_REQUEST_t));

nebo nedělej alokaci jednotlivych struktur a nacpi do pole referenci na strukturů 

TASK_REQUEST_t* requests = (TASK_REQUEST_t *) malloc(3 * sizeof(TASK_REQUEST_t));
requests[0] = TASK_REQUEST_t();
Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
KIIV
~ Moderátor
+43
God of flame
5. 4. 2015   #12
-
0
-

#10 oxidián
protoze je ku*va rozdil mezi:

w->task.requests = malloc

a

w->task.requests[neco] = malloc

Nahlásit jako SPAM
IP: 93.91.152.–
Program vždy dělá to co naprogramujete, ne to co chcete...
ondrej39+1
Věrný člen
5. 4. 2015   #13
-
0
-

#6 PiranhaGreg
Řešil jsem to tu pár měsiců zpátky s KIIVem, když jsme rozebírali knihovnu vector. Malloc se ti možná nelíbí, ale pro alokaci více objektů v C++ je mnohem lepší, protože nevolá implicitní konstruktor, zatímco new z C++ ano.

A i když budeš alokovat 1000 objektů, tak nevolat 1000 konstruktorů je prostě rychlejší, než kdybys je volal.

Nahlásit jako SPAM
IP: 46.39.172.–
Inject all the dependencies!
oxidián0
Grafoman
5. 4. 2015   #14
-
0
-

#11 ingiraxo
Já to nechápu. Já nechci dvourozměrné pole, ale jednorozměrné. Je to dynamické, ale při současné konfuguraci budu tam mít 10 struktur.

TASK_REQUEST_t * requests;

Možná by se to vůbec nemělo alokovat. Tahle alokace je uvnitř cyklu. Před tím cyklem mám

w->task.requests = (TASK_REQUEST_t *) malloc (w->task.pointers_count * sizeof(int) );

Nemělo by to tedy být alokováno jen jednou před cyklem a počítat s velikostí struktury místo velikosti pointeru?

w->task.requests = (TASK_REQUEST_t *) malloc (w->task.pointers_count * sizeof(TASK_REQUEST_t) );

Dneska mi to vůbec nemyslí, asi jsem měl moc velkou pauzu od programování.

Nahlásit jako SPAM
IP: 78.45.199.–
ingiraxo+15
Grafoman
5. 4. 2015   #15
-
0
-

#14 oxidián
to první co jsem psal NENI dvojrozměrné pole, ale alokované pole a ukazateli na alokované prvky, pak jsem psal, že je pro tebe asi lepší použít to dtruhý, kde jen alokuješ velikost pole a prvky nebudes alokovat (takže v toho řádku 102 vyhodíš malloc)

// tohle je třeba špatně!
// alokuješ pole typu INT a rves do toho strukturu...
w->task.requests = (TASK_REQUEST_t *) malloc (w->task.pointers_count * sizeof(int) );

// správně
w->task.requests = (TASK_REQUEST_t *) malloc (w->task.pointers_count * sizeof(TASK_REQUEST_t));


V tom cyklu potom budeš mít 

TASK_REQUEST_t x;
x.neco = ...

w->task.requests[0] = x;

a rozhodně přejmenovat proměnnou "pointers_count" na "count"

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
PiranhaGreg0
Stálý člen
5. 4. 2015   #16
-
0
-

#13 ondrej39
Já nepsal že se mi malloc nelíbí. Většinu času píšu v C  . Jinak C++ má taky obecný new, který vrací void *. A pokud už alokuješ pole s nějakou větší strukturou/třídou, tak se volání implicitního konstruktoru provede jen pokud je to nutný. Takže rychlost s new oproti mallocu rozhodně neztratíš.

Jediný, co new nezvládá, tak je realokace...

Nahlásit jako SPAM
IP: 109.81.210.–
ingiraxo+15
Grafoman
5. 4. 2015   #17
-
0
-

#13 ondrej39
to záleží... všeobecně používání new nic neztratíš, protože:
1) volá se pouze bezparametrický konstruktor, takže když ho odebereš, tak se ti nic volat nebude
2) je dobré, mít nějaký výchozí hodnoty objektu při jeho vytvoření, stejně by si je nastavoval dodatečně nebo později
3) jestli se v nekterých případech konstruktor nevolá si nejsem ze 100% jistej, ale pokud je to komplexní objekt a má v konstruktoru plno dalších volání, tak je možný, že jak psal Piranha se přeskočí, ale to bych tipnul, že bude potřeba nastavit v kompilátoru.. bylo by dost chaotický, kdyby někdy zavolal konstruktor a někdy ne

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
ondrej39+1
Věrný člen
5. 4. 2015   #18
-
0
-

#16 PiranhaGreg
Omlouvám se oxidiánovi za OT: Kompiluji ve Visual Studiu a když si pomocí new vytvořím pole třeba o 10 objektech (Objekt * pObkejt = new Objekt[10];), tak se mi konstruktor protě 10× zavolá.

Předpokládám, že ve std::vectoru malloc a placement new pro alokaci nepoužívají jen kvůli tomu, aby byl kód složitější, ale že jejich použití bude mít zřejmé opodstatnění.

Nahlásit jako SPAM
IP: 46.39.172.–
Inject all the dependencies!
oxidián0
Grafoman
5. 4. 2015   #19
-
0
-

#15 ingiraxo
Takže je to tak jak jsem se domníval ve svém posledním příspěvku. Jak říkám, už se mi to vykouřilo z hlavy, chce to více praxe na zapamatování. Prostě když deklaruju proměnnou kde je jeden pointer * tak tam budu při alokaci počítat s velikostí toho typu, který chci použít a bude to pole typů. Když by to bylo dvourozměrné pole, tak proměnnoé budu deklarovat dva pointery ** a při alokaci před cyklem počítám velikost pointeru, pak uvnitř cyklu při alokaci počítám s velikostí typu.

Zkrátka, mýlně jsem se domníval, že když je při deklaraci jeden pointer, tak při alokaci se bude počítat s pointerem...

Tak díky a už to funguje.

Nahlásit jako SPAM
IP: 78.45.199.–
ingiraxo+15
Grafoman
5. 4. 2015   #20
-
0
-
Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
oxidián0
Grafoman
5. 4. 2015   #21
-
0
-

#18 ondrej39
Ještě že jsem ten VS napodruhé nanainstaloval (chyba během instalace). Jsem rád že jsem se do C++ nepouštěl, ušetřilo mi to mraky času. C++ je pro mě příliš vysoký level. Zatím. Ale předpokládám že C je rychlejší  než C++ protože se všemi těmi komplikovanými věcmi jako jsou namespacy, šablony, třídy to prostě musí být pomalejší než C. Jsem takhle srovnával kdysi v PHP programy které byly napsané v OOP byly o dost pomalejší než obyčejné  jednoduché funkce. On ten rozdíl nemusí být moc vidět, ale myslím že při práci s rastry, kde vykonáváš smyčky třeba o 4 milionech cyklů by to znát být mohlo. C++ chápu že se hodí dobře na psaní grafických aplikací, kde ten rozdíl moc nepoznáš protože si všechno naklikáš, takže ztrávíš deset minut konfigurací a pak teprve několik sekund výpočtem.

Nahlásit jako SPAM
IP: 78.45.199.–
ondrej39+1
Věrný člen
5. 4. 2015   #22
-
0
-

#20 ingiraxo
Akorát jsi potvrdil to, co tady píšu. New volá konstruktor, a to bezparametrický. A pokud bezparametrický konstruktor smažeš třeba pomocí delete, tak ti new daného objektu nepůjde vůbec.

#include "stdafx.h"
#include <iostream>
#include <vector>

class Objekt
{
public:
	Objekt()
	{
		std::cout << "Vytvarim objekt na adrese " << this << std::endl;
	}
protected:
private:

};

int _tmain(int argc, _TCHAR* argv[])
{
	Objekt * pObjekt = new Objekt[10];

	std::cout << std::endl;
	std::cout << "Vytvarim vector tridy \"Objekt\"...\n" << std::endl;

	std::vector<Objekt> v;

	std::cout << "Rezervuji misto na 1000 objektu tridy Objekt...\n" << std::endl;
	v.reserve(1000);

	std::cout << "Vkladam objekty do vektoru...\n" << std::endl;
	v.push_back(Objekt());
	v.push_back(Objekt());
	v.push_back(Objekt());
	v.push_back(Objekt());
	v.push_back(Objekt());
	
	return 0;
}

//vystup
Vytvarim objekt na adrese 005432C0
Vytvarim objekt na adrese 005432C1
Vytvarim objekt na adrese 005432C2
Vytvarim objekt na adrese 005432C3
Vytvarim objekt na adrese 005432C4
Vytvarim objekt na adrese 005432C5
Vytvarim objekt na adrese 005432C6
Vytvarim objekt na adrese 005432C7
Vytvarim objekt na adrese 005432C8
Vytvarim objekt na adrese 005432C9

Vytvarim vector tridy "Objekt"...

Rezervuji misto na 1000 objektu tridy Objekt...

Vkladam objekty do vektoru...

Vytvarim objekt na adrese 0024FB2F
Vytvarim objekt na adrese 0024FB3B
Vytvarim objekt na adrese 0024FB47
Vytvarim objekt na adrese 0024FB53
Vytvarim objekt na adrese 0024FB5F
Nahlásit jako SPAM
IP: 46.39.172.–
Inject all the dependencies!
ingiraxo+15
Grafoman
5. 4. 2015   #23
-
0
-

#21 oxidián
mám dojem, že máš trochu milné informace nebo aspon neaktuální, mezi C++ a těž už c++14 je dost změn a nejen to,i původní C++ se v rychlosti moc nelyší, pokud vůbec nějak viditelně

to je to samé, jako když někdo řekne, že java je pomalá a přitom je srovnatelná s C.

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
oxidián0
Grafoman
5. 4. 2015   #24
-
0
-

#23 ingiraxo
Tak to byl jen předpoklad. Nemám to potvrzené. Těžko psát jeden program dvakrát jednou v Cčku a podruhé v C++ (zvlášť když C++ rozumím prdlačku).

Nahlásit jako SPAM
IP: 78.45.199.–
ondrej39+1
Věrný člen
5. 4. 2015   #25
-
0
-

#24 oxidián
Na C++ je skvělé to, že můžeš používat vše co znáš z C a ještě něco navíc.   

Nahlásit jako SPAM
IP: 46.39.172.–
Inject all the dependencies!
ingiraxo+15
Grafoman
5. 4. 2015   #26
-
0
-

#22 ondrej39
přesně, vždy potřebuješ konstruktor při použití new ať už bezparametrickej nebo vlastní s parametrem (třeba i blbej copy constructor).. ale daleko větší výhodu vidim v dealokaci, kde destruktor řeší celý zřetězený struktůry, co by při free() bylo komplikovaný a snadno člověk zapomene, zda uvolnil všechno 

struct Content
{
    int value;

    Content() : value(0) {
        cout << "Content\n";
    }
    ~Content() {
        cout << "Delete Content\n";
    }
};

class Parent
{
public:
    Parent() : percent(100), content(new Content()) {
        cout << "Parent\n";
    }
    virtual ~Parent()
    {
        delete content;
        cout << "Delete Parent\n";
    }
protected:
    float percent;
    Content* content;
};

class A : public Parent
{
public:
    A() {
        cout << "A\n";
    }
    ~A() {
        cout << "Delete A\n";
    }
};

int main()
{
    Parent* arr = new A[3];
    delete[] arr;
    return EXIT_SUCCESS;
}

výstup potom je 

Content
Parent
A
Content
Parent
A
Content
Parent
A
Delete A
Delete Content
Delete Parent
Delete A
Delete Content
Delete Parent
Delete A
Delete Content
Delete Parent
Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
ondrej39+1
Věrný člen
5. 4. 2015   #27
-
0
-

#26 ingiraxo
V reálné situaci ale nikdy nebudeš nějak náhodně alokovat místo na haldě. Od toho jsou v C++ objekty a RAII, abys to svinstvo, v němž by mohlo dojít k opominutí uvolnení, zabalil do uživatelsky přívětivějšího obalu.

Mně se new líbí daleko více než malloc, je to pro mě jako člověka, který ve škole na C++ začínal a C měl až v dalším semestru (Buh-ví-proč) mnohem příjemnější, ale pokud prostě konstruktory při alokaci volat nechceš, pak ti pravděpodobně nic jiného než malloc/calloc s následným placement new nezbyde.

A ve finále ani to dělat nemusíš, protože vector už je dávno udělanej za tebe.   

Nahlásit jako SPAM
IP: 46.39.172.–
Inject all the dependencies!
oxidián0
Grafoman
5. 4. 2015   #28
-
0
-

#25 ondrej39
To mi psát nemusíš nevím čeho tím chceš dosáhnout.

Nahlásit jako SPAM
IP: 78.45.199.–
oxidián0
Grafoman
5. 4. 2015   #29
-
0
-

Když už jsme offtopic existuje nějaká funkce v C která funguje podobně jako strchr ale zadal bych tam více znaků, které hledám? Chci najít pozici výskytu znaku + nebo -. Mám teď v kódu strtok, respektive strTok (bezpečná verze strtok) a jako oddělovač jsem použil const char scol[3] = "+-"; problémem je že tím se ze stringu vytratí + nebo - takže nezjistím co tam bylo. Takže bych to předělal, aby to našlo znak + nebo - a dostal bych řetězec až po ten hledaný znak. Tím pádem pak vím co se nachází na daném místě jestli + nebo - a pak jen posunu ukazatel na ten znak.

PS: moderátor by mohl přepsat název této diskuse aby obsahoval název chyby: incompatible types when assigning to type (structure) from type void

já se totiž unáhlil s odesláním
 

Nahlásit jako SPAM
IP: 78.45.199.–
oxidián0
Grafoman
6. 4. 2015   #30
-
0
-

mám vyřešeno

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

#18 ondrej39
uz minule jsem si ten malloc radeji overoval a neni tam pouzit - je tam new void[]. (Nicmene podle gdb je to beztak pozdeji podchycene na dalsich urovnich pomoci mallocu/free)

#23 ingiraxo
C muze byt i pomalejsi nez Java.. Obzvlaste, kdyz zarytej Javista, co nema s C zadne zkusenosti, zacne delat srovnavaci testy. Kdyz se to pak naimplementuje stejnym zpusobem, tak v C to znamena e^x algoritmy a podobne). Treba na jednom webu jsou zadani jako nacitat milion cisel v rozsahu 0-1000000 a s javou se proste pod asi 2 sekundy nikdo nikdy nedostal. V C++ se zase nedostali na velkou rychlost pokud pouzivali iostream. (to same pro cstdio, kdyz nechali zaplou synchronizaci mezi iostreamem a cstdio)

A jelikoz v jave neexistuje nic jako kompaktni pole, tak nemuzes nikdy v zivote jet treba az na uroven optimalizace pro cache prediction. (v c++ se nakonec pouziva vector i pro nahodne odmazavani/pridavani - protoze najit misto pro vlozeni v seznamu je pomaly - pomalejsi nez presouvat bloky pameti ve vectoru)

Nahlásit jako SPAM
IP: 93.91.152.–
Program vždy dělá to co naprogramujete, ne to co chcete...
PiranhaGreg0
Stálý člen
6. 4. 2015   #32
-
0
-

Hlavně je mnohem důležitější vybrat správný algoritmus a pak teprve jazyk. Spoustu úloh lze díky binárnímu hledání snížit na složitost, kde figuruje logaritmus. Docela často vidím, jak má někdo v C++ kódu rádoby optimalizace, ale používá úplně naivní algoritmus.

Nahlásit jako SPAM
IP: 109.81.210.–
oxidián0
Grafoman
6. 4. 2015   #33
-
0
-

#31 KIIV
To by mě zajímalo jak vkládáš dvě odpovědi do jednoho příspěvku. Já to jen zkopíruji ale tím se ztratí link na příspěvek

Nahlásit jako SPAM
IP: 78.45.199.–
ingiraxo+15
Grafoman
6. 4. 2015   #34
-
0
-

#33 oxidián
klikne 2x na odpovědět?

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
oxidián0
Grafoman
24. 4. 2015   #35
-
0
-

Mám chybu:

warning: passing argument 2 of 'sprintf' makes pointer from integer without a cast

a nemohu pochopit odkud se bere ten integer. Funkce by měla vracet const char * a sprintf taky v druhém argumentu má příjmout const char * tak v čem je problém?

typedef enum {
    TSS_TB_ERROR=-1,
    TSS_LR_ERROR=-2,
    TSS_CHAR_ERROR=-3,
    TSS_TYPE_ERROR=-4
    } TASK_SUB_SQUARE_ERRORS_t;
#define taskSubSquare_errors (const char*[4]){"cannot use t&b", "cannot use l&r", "incorrect character","type unspecified"  }
const char * getSubSquareError(const int error){
    return taskSubSquare_errors[abs(error)-1];
}
sprintf(w->pErrorMessage,getSubSquareError(result));
Nahlásit jako SPAM
IP: 78.45.87.–
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, 60 hostů

Podobná vlákna

Chyba v IF — založil Kolcek

Chyba v c — založil bohetik

Chyba — založil Sheldon

Chyba C++ — založil AnonImouS

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ý