Výpočet přes celou strukturu – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu
Reklama
Reklama

Výpočet přes celou strukturu – C / C++ – Fórum – Programujte.comVýpočet přes celou strukturu – C / C++ – Fórum – Programujte.com

 

Hledá se programátor! Plat 1 800 € + bonusy (firma Boxmol.com)
Patrik
~ Anonymní uživatel
106 příspěvků
28. 5. 2014   #1
-
0
-

Ahoj,

řekněme, že mám strukturu a chci vypočítat součet prvků dané struktury. Nechci to, ale počítat po jednotlivých členech, ale přes celou strukturu, řekněme třeba přes for cyklus (naznačeno v mainu). Nedá se nějak využít ukazatele, který by se posunul nějak na další prvek? Či jak bych toto mohl udělat?

typedef struct

 int    a;      
 short int b;      
 uint8_t   c;    
 uint8_t   d;   
 uint32_t  e;         
 uint32_t  f;       
} foo;

 int main(void)
 {
 foo *f, f_p;
 int soucet;

 f = &f_p;

 f->a = 1;
 f->b = 2;
 f->c = 3;
 f->d = 4;
 f->e = 5;
 f->f = 6;


 for(int i = 0; i < sizeof(foo);i++)
 {
  soucet += *f;
 }

    return 0;
 }

S pozdravem

Patrik

Nahlásit jako SPAM
IP: 94.113.242.–
Reklama
Reklama
KIIV+42
God of flame
28. 5. 2014   #2
-
0
-

cyklem by to mozna slo, pokud bys mel stejnou sirku polozek.. bez toho to proste musis delat po jednotlivejch polozkach

kazdopadne nechapu k cemu by ti to bylo.. nejaka predcasna optimalizace ci co?

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Patrik
~ Anonymní uživatel
106 příspěvků
2. 6. 2014   #3
-
0
-

Ahoj,

já potřebuju vypočítat CRC přes jednotlivé položky ve struktuře. Ve stylu crc(stuktura, velikost struktur);. Takže mě zajímá zda se můžu v té struktuře nějak pohybovat, abych to nemusel počítat přes jednotlivé položky. Nic mě, ale nenapadá, jen to jestli nejde nějak ten ukazatel posunovat?

Nahlásit jako SPAM
IP: 94.113.242.–
hlucheucho+10
Posthunter
2. 6. 2014   #4
-
0
-

Možná by šlo strukturu považovat za pole bytů a udělat jeho CRC. S přetypováním ukazatele by to mělo jít, možná trochu prasárna.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Patrik
~ Anonymní uživatel
106 příspěvků
2. 6. 2014   #5
-
0
-

Ahoj,

nemůžeš sem dát nástřel té myšlenky struktury jako pole bytů a přetypování ukazatele?

Patrik

Nahlásit jako SPAM
IP: 94.113.242.–
hlucheucho+10
Posthunter
2. 6. 2014   #6
-
0
-

Vhodnější je union

	typedef struct{
		int a;
		char b, c;
		float x;
	} mystruct;

	typedef union {
	   mystruct s;
	   byte b[sizeof(mystruct)];
	}  myunion;

	myunion neco;
	byte sum = 0;

	neco.s.a = 56;      //prace se strukturou
	neco.s.x = 3.25;

	for (int i = 0; i < 10; i++) {  //prace s polem
	   sum += neco.b[i];
	}

union ti umožní ke stejnému kusu paměti přistupovat jako k různým datovým typům, v příkladu jako ke struktuře a stejně velkému poli bytů.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
vitamin+8
Grafoman
2. 6. 2014   #7
-
0
-

#5 Patrik
Akym sposobom chces pouzivat ten sucet? (ak ako hash tak treba brat do uvahy aj alignment).

Nahlásit jako SPAM
IP: 195.28.77.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
Patrik
~ Anonymní uživatel
106 příspěvků
2. 6. 2014   #8
-
0
-

#7 vitamin

Ahoj,

já potřebuju potom ty jednotlivé položky brát po osmy bitech. Takže klidně by šlo i něco ve stylu, že by se vždy postupně ze struktury bralo vždy osm bitů..... Možná by to šlo udělat i jinak než výše zmíněné.

Nahlásit jako SPAM
IP: 94.113.242.–
KIIV+42
God of flame
2. 6. 2014   #9
-
0
-

#8 Patrik
tak 8bitu.. to je po bajtech.. jen opravdu hrozi, ze bude struktura zarovnana podle sirky sbernice a tim bys dostal na ruznych platformach pro stejny cisla ruzne CRC... (a to samy se muze stat pri prechodech mezi 8/16/32/64b procesorama i s datovejma typama jako short int, int a tak)

jinak to jde i tim pretypovanim:     uint8_t * test = (uint8_t *)&f_p;

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Patrik
~ Anonymní uživatel
106 příspěvků
3. 6. 2014   #10
-
0
-

Ahoj,

pokusím se to vyřešit tím přetypováním, ale mám ještě problém, že ty čísla se ukládají ve formátu little endian a já bych to potřeboval ukládat ve formátu big endian. Jednotlivé položky bych potřeboval ihned takto do pole uložit, protože měnit to až po uložení do pole je nesmyslné a nereálné. Jen mě nějak nenapadá, jak na to při tomto přetypování.  

Nahlásit jako SPAM
IP: 94.113.242.–
hlucheucho+10
Posthunter
3. 6. 2014   #11
-
0
-

Endianita jde u překladače nastavit, aspoň u těch, co znám. Akorát je třeba vědět, jestli pro danou aplikaci není zadána a nelze ji z nějakého důvodu měnit.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
hlucheucho+10
Posthunter
3. 6. 2014   #12
-
0
-

K výčtu úskalí ještě přidám implementačně závislou velikost u datového typu int.

Napadá mne obsah struktury zformátovat do řetězce a udělat kontrolní součet řetězce. Tím se vyhneš problémům se zarovnáváním a endianitou.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Patrik
~ Anonymní uživatel
106 příspěvků
3. 6. 2014   #13
-
0
-

#12 hlucheucho
Do textového řetězce? Při sčítání se to bude muset zase převádět zpět na čísla pomocí atoi či tak. To se mi zdá dost nešťastné řešení. Nebo to nechápu.

Nahlásit jako SPAM
IP: 94.113.242.–
ondra.holub+1
Stálý člen
3. 6. 2014   #14
-
0
-

#1 Patrik
Hlavně je dobré si uvědomit, že při zarovnání můžou být mezi jednotlivými prvky mezery (nevyužité bajty). A pak nemusí být dvě struktury se stejným obsahem binárně shodné (binárně podle požadovaného principu).

Pokud např. uvedenou strukturu trošku přeskládám, můžu dostat toto:

#include <inttypes.h>
#include <iostream>

struct foo
{
    int    a;
    short int b;
    uint32_t  e;
    uint8_t   c;
    uint8_t   d;
    uint32_t  f;
};

void dump(void* data)
{
    const uint8_t* d = (uint8_t*)data;

    for (unsigned i = 0; i < sizeof(foo); ++i)
        std::cout << (int)d[i] << ' ';
    std::cout << '\n';
}

void test(int index)
{
    {
        foo f;
        f.a = 10;
        f.b = 20;
        f.c = 30;
        f.d = 40;
        f.e = 50;
        f.f = 60;

        dump(&f);
    }

    {
        {
            uint8_t a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
            for (int i = 0; i < index && i < sizeof(a) / sizeof(*a); ++i)
                std::cout << (int)a[i] << ' ';
            std::cout << '\n';
        }

        foo f;
        f.a = 10;
        f.b = 20;
        f.c = 30;
        f.d = 40;
        f.e = 50;
        f.f = 60;

        dump(&f);
    }
}

int main()
{
    test(5);
}


Přestože jsou obě struktury f obsahově stejné, může být výsledek programu např. tento:

10 0 0 0 20 0 0 0 50 0 0 0 30 40 0 0 60 0 0 0
1 2 3 4 5
10 0 0 0 20 0 7 8 50 0 0 0 30 40 15 16 60 0 0 0

Je vidět, že první řádek se se třetím neshoduje, protože ve druhém případě mezery mezi prvky struktury obsahují smetí, které zůstalo na zásobníku po předchozích proměnných. Výsledek se navíc může lišit podle platformy, překladače, verze překladače, parametrů překladu...

Pro tento příklad jsem data ve struktuře lehce zpřeházel, abych docílil mezer, ale i bez zpřeházení vzhledem k výše zmiňované nejisté velikosti int je výsledek nejednoznačný.

Nahlásit jako SPAM
IP: 194.138.12.–
hlucheucho+10
Posthunter
3. 6. 2014   #15
-
0
-

u řetězce uděláš CRC znaků, tento postup se používá u komunikace s regulátory Omron (tuším, že protokol Modbus). CRC z řetězce znaků má výhodu - odpadá celá řada problémů vznikajících ze závislosti na platformě a implementaci.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Satik
~ Anonymní uživatel
120 příspěvků
3. 6. 2014   #16
-
0
-

#15 hlucheucho

Pokud to není něco, co je časově kritické, pak ty řetězce jsou dobrá volba (jen případně bacha na floaty - tečka vs čárka).

Zauvažoval bych i nad změnou zarovnání dané struktury - např. v MSVC přes #pragma pack http://msdn.microsoft.com/en-us/library/2e70t5y1.aspx , pokud to kompilátor, který používá, podporuje a máš jak zaručit všude stejný Endian.

Pak stačí vzít jen strukturu jako pole bajtů a spočítat hash z něho.

Nahlásit jako SPAM
IP: 86.49.188.–
hlucheucho+10
Posthunter
3. 6. 2014   #17
-
0
-

čísla se ukládají ve formátu little endian a já bych to potřeboval ukládat ve formátu big endian.

Z jakého důvodu? Půjde o přenos dat do jiného systému? Endianita, zarovnávání a velikost datového typu int budou představovat těžko řešitelný problém. V takovém případě bych strukturu přenášel jako řetězec znaků a CRC nebo jiný kontrolní mechanismus prováděl nad tímto řetězcem. Ostatně se to tak dělá u komunikačních protokolů na RS485 a to i s přístroji kde použitý jednočip nemá k dispozici moc početního výkonu. Jako bonus získáš možnost použít řídící znaky viz dolní část ASCII tabulky.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
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, 106 hostů

Moderátoři diskuze

 

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