Tudom, nagyon elvetélt ötlet, de kíváncsi vagyok, hogy lehet-e például egy '3 bájtos mutatót létrehozni' (azaz olyan mutatót, amit ha növelek, 3 bájttal magasabb címre mutat)? Hasznos lenne például 24 bites BMP képek manipulálásához, mert (azt hiszem) gyorsabban és egyszerűbben elérném vele az adatot, mintha bájtonként pakolgatnám a pixeleket. (1 pixel = 3 bájt)
Alternatív ötletek is jöhetnek persze, de kérlek vegyétek figyelembe, hogy az ANSI C szabványnak megfelelően szeretném megírni a kódot.
- 1440 megtekintés
Hozzászólások
Jó ötlet, de nincs ötletem, így feliratkozom. :)
------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.
- A hozzászóláshoz be kell jelentkezni
Mi van? Nem értem.
unsigned char *pixelbuff;
pixelbuff+=3;
Hol itt a probléma?!?
- A hozzászóláshoz be kell jelentkezni
Ez by design így működik. Egy int* esetén a ++ az 4 bájtot léptet, egy char* esetén 1-et.
- A hozzászóláshoz be kell jelentkezni
Pont harom bajtosat meg ugyse fog kapni, a 3 az nem kerek szam, 2 vagy 4.
--
()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.
- A hozzászóláshoz be kell jelentkezni
// sizeof( RBG ) == 3 byte
struct RGB
{
char R;
char G;
char B;
};
RGB * rgbBuf;
// inicializalas, etc. [ ... ]
++rgbBuf; // 1 elemet, azaz 3 bajtot leptet
Mi ezzel a gond?
----------------------
while (!sleep) sheep++;
- A hozzászóláshoz be kell jelentkezni
a struct igazitas lehet a gond, mert R es G koze filler byte-ok kerulhetnek
egyebkent ugyanakkor kuldtuk be hehe
- A hozzászóláshoz be kell jelentkezni
A "__packed__" megoldja ezt a problémát, de az nincs benne az ANSI C szabványban tudtommal.
- A hozzászóláshoz be kell jelentkezni
jaja, de lehetne bitfieldet csinálni, akkor nem alignolja.
az meg ansi c.
typedef struct {
unsigned char R : 8;
unsigned char G; 8;
unsigned char B: 8;
} tRGBpixel;
Ha minden igaz, ez így pont 24 bit lesz, és nem lesz alignolva.
tRGBPixel *rgbBuffer = malloc(....);
- A hozzászóláshoz be kell jelentkezni
#include <stdio.h>
struct RGB_t {
char rgb[3];
};
int main()
{
RGB_t buf[100];
RGB_t *p1 = buf;
printf( "%d %d %d\n", sizeof(RGB_t), p1, p1+1 );
return 0;
}
nem tudom, hogy a struct igazitas / minimum struct meret bezavarhat-e
talan nem
- A hozzászóláshoz be kell jelentkezni
Mondjuk mi mintha C++-t irtunk volna,
// sizeof( RBG ) == 3 byte
struct RGB
{
char R;
char G;
char B;
};
int main( )
{
struct RGB * rgbBuf;
// inicializalas, etc. [ ... ]
++rgbBuf; // 1 elemet, azaz 3 bajtot leptet
}
Talan ez a korrekt C, de igazabol kevesse emlekszem a pontos szintaktikara a C structok eseteben.
----------------------
while (!sleep) sheep++
- A hozzászóláshoz be kell jelentkezni
A struktúra így valóban C-szerűbb, mint ahogy az előbb írtad.
[TROLL ON]
A "//" komment viszont nem ANSI C szabvány. :P
[TROLL OFF]
- A hozzászóláshoz be kell jelentkezni
BMP feldolgozasnal (binaris adat) erdemes lenne unsigned char-ral dolgozni, igy nem csak 128-ig latna a szineket.
--
()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.
- A hozzászóláshoz be kell jelentkezni
A C99-es szabvány (habár az már nem ANSI...) stdint.h headerében van 1,2,4 és 8 bájtos garantált méretű típus, de sajnos 3 bájtos nincs. Amúgy én is a struct-ra gondoltam még, de azt már írták előttem.
- A hozzászóláshoz be kell jelentkezni
Köszönöm a hozzászólásokat!
Kicsit ködösen fogalmaztam, mert igaz, hogy a címzés megkönnyítésére kerestem ( és találtam ) választ, de igazán a cél az lenne, hogy ne bájtról-bájtra kelljen adatot másolni ( skaláris típusokkal ), hanem közvetlenül, mint pl. az
( int ) egyik_valtozo = ( int ) masik_valtozo
esetén egyszerre ugye 4 bájtot mozgat. Én hasonlót szeretnék, de 3 bájtos típusokkal megoldani, hogy az ilyen jellegű hosszas megoldásokat elkerüljem:
http://www.libsdl.org/cgi/docwiki.cgi/Pixel_Access
( a 3 bpp-vel kapcsolatos részeket kell figyelni )
Köztes megoldás ugyan van ( lásd a példa ), csak ezzel az a gond, hogy az utolsó pixel értékadásánál nem kívánt memóriaterületre is írunk:
#include stdio.h
#include stdlib.h
int main( void )
{
int
szelesseg = 3,
magassag = 3,
x = 0,
y = 0;
void
*buff = (unsigned char *)
malloc( (size_t) magassag * szelesseg*3 );
printf( "buff kezdete : %p\n"
"buff vege : %p\n\n",
buff,
buff + (magassag * szelesseg*3) - 1
);
for( y = 0 ; y < magassag ; ++y )
{
/* Ertekadas. */
for( x = 0 ; x < szelesseg ; ++x )
*(int *)(buff + (y * szelesseg*3) + (x*3)) = 0x58424752;
/* X B G R
* az X csak egy jel*/
/* Kiiratas. */
for( x = 0 ; x < szelesseg*3 ; ++x )
printf( "%p : %c\n",
(buff + (y * szelesseg*3) + x),
*(char *)(buff + (y * szelesseg*3) + x)
);
printf( "\n" );
}
printf( "%p : %c\n",
(buff + ((y-1) * szelesseg*3) + x),
*(char *)(buff + ((y-1) * szelesseg*3) + x)
);
free( buff );
return( 0 );
}
--
Azt akarom, hogy az emberek ne kényszerből tanuljanak, hanem azért, mert tudni akarnak.
- A hozzászóláshoz be kell jelentkezni
hogy ne bájtról-bájtra kelljen adatot másolni ( skaláris típusokkal ), hanem közvetlenül
Ilyen nincs.
Bár nem tudom, hogy miért akarsz mást, mint bájtról-bájtra másolni.
Ha a hatékonyság a gond, akkor nem tudod elkerülni a kézzel, jól kiszámított módon megírt memcpy-t, legfeljebb becsomagolod valamibe, hogy ne legyen annyira randa.
Ha a "látványra" gyúrsz, akkor tessék függvényt írni (vagy c++ esetén objektum + metódus), és akkor a függvény/metódus hívása szép lesz, azon belül viszont a csúnyaság megmarad.
És engedtessék meg még egy megjegyzés: nagyon sok cpu van (nagyjából már egy 486-os is ez a kategória, onnan fölfele meg pláne), ahol jó esélyed van rá, hogy a 4-bájtos struct/int kezelése fényévekkel gyorsabb, mint ha összepakolod 3-bájtos távolságra, egymás mellé a rekordokat, és próbálsz 3 bájtonként szívni. A cpu ugyanis rendelkezik olyan utasítással, ami egy 4-bájtos wordöt egyben beolvas, kiír, viszont 3 bájt mozgatása több utasítást fog igényelni.
- A hozzászóláshoz be kell jelentkezni
A gyorsaság miatt szeretném kiváltani a bájtok egyenkénti másolását, például azzal, hogy egy int típust mozgatok egy char helyett (lásd a kódot).
nagyon sok cpu van (...), ahol jó esélyed van rá, hogy a 4-bájtos struct/int kezelése fényévekkel gyorsabb
Erre konkrét kódot tudnál mutatni, mert nem egészen értem.
A függvényhívásokkal az a bajom, hogy az plusz órajelekbe kerül, ezért nem tudom, mennyire hatékony, de most kipróbálom és legalább olyan gyors, mint a helyben megírt kód, akkor van egy újabb megértendő dolog a C-ben, aminek utánna kell járnom...
--
Azt akarom, hogy az emberek ne kényszerből tanuljanak, hanem azért, mert tudni akarnak.
- A hozzászóláshoz be kell jelentkezni
Mivel a procid 32b-es ezért 32b-es adatokkal érzi magát igazán jól, de 24b-essel semmiképpen. Általában egyszerűbb és hatékonyabb 32b-es változót használni arra is.
Gyakorlati példa: van egy for ciklusod ami csak - hasraütve - 112* kell, hogy lefusson, mégsem fogsz byte típust használni, mert az int gyakorlatilag gyorsabb és a memória használatot ebben az esetben elfelejtheted (főleg, hogy jó esetben a processzor regiszteréből soha sem fog kikerülni).
A függvényhívásokról csak annyit, hogy ha úgy optimálisabb (kevés helyen van használva, nagyon rövid, stb.) úgyis lerendezi a fordító. Ha meg mindenhova raksz egy rakás különféle kódot akkor kis szerencsével a processzor cache megtelése miatt elveszted az előnyt. Sajnos az optimalizálás nem is olyan egyszerű...
- A hozzászóláshoz be kell jelentkezni
arra utal a kollega, hogy a processorok csak szohatarokrol tudnak altalaban olvasni gyorsan (risc gepek neha meg lassan sem)
--
NetBSD - Simplicity is prerequisite for reliability
- A hozzászóláshoz be kell jelentkezni
Erre konkrét kódot tudnál mutatni, mert nem egészen értem.
A >=386-os cpu tud egyszerre 1, 2 vagy 4 byte-ot mozgatni egy assembly utasítással. A normál 32-bites üzemmódokban a 4 byte-os mozgatásos utasítás X byte hosszú (ez az alap), az 1 byte-os mozgatásos szintén, de a 2-byte-os mozgatás egy byte-tal hosszabb assembly kód. 3 byte-ot két utasításban lehet mozgatni (egy 1 és egy 2 byte-os mozgatás), a két utasítás 2*X + 1 byte hosszú kód lesz, végrehajtási időben pedig min. 2-szer annyi idő (az 1 és a 2 byte-os művelet ugyanazt a cache sort érinti, azokat csak egymás után lehet végrehajtani). Tehát több mint duplájára sikerült növelni a kód méretét (és így a beolvasásához szükséges időt is) és a végrehajtási időt is.
- A hozzászóláshoz be kell jelentkezni
Azert akad itt néhány probléma:
- a kód épit a proci byte sorrendjére. Egy big-endian procin a kódod furcsa dolgokat fog művelni.
- sok CPU (pl ARM) nem képes 32 bit széles értékeket nem 4 byte -ra igazitott cimről olvasni. Jó esetben kapsz egy data abort exceptiont, rossz esetben csak hibás adatot olvas a proci. Azér az emlitésre méltó, hogy az X86 is sokkal gyorsabban olvas, ha megfelelően igazitott cimrol olvasol. Legalabbis a 486 -nal ez még számitott.
- a kód feltételezi hogy az int 32 bit széles. Próbáld meg leforditani 64 bites CPU -ra. Használj inkább uint32_t tipust.
1 és (részben) 2 tárgytalan, ha PC -re irod a kódot, és sosem akarod majd már CPU -un futtatni. 3. ponttal azonban PC -n is problémád lehet.
- A hozzászóláshoz be kell jelentkezni
A sima int 32 bit-es x86_64-en. Ami változott az a long int és a pointer mérete.
- A hozzászóláshoz be kell jelentkezni
"hogy ne bájtról-bájtra kelljen adatot másolni ( skaláris típusokkal ), hanem közvetlenül, mint pl. az
( int ) egyik_valtozo = ( int ) masik_valtozo"
memcpy?
- A hozzászóláshoz be kell jelentkezni
Kicsit lassabb az értékadáshoz képest...
--
Azt akarom, hogy az emberek ne kényszerből tanuljanak, hanem azért, mert tudni akarnak.
- A hozzászóláshoz be kell jelentkezni
Bitmaszkolásra gondoltál már 4 bytes változóval, ahol az utolsó byte kihasználatlan? Így van egy 4 bytes egységed, amit tudsz makrókkal manipulálni. Mondjuk valami ilyesmi:
uint32_t rgb; /* UUUUUUUURRRRRRRRGGGGGGGGBBBBBBBB */
#define GET_RED (rgb >> 16);
#define SET_RED(x) ((x << 16) & rgb);
...
A sima uint_32_t változót meg egyszerűen tudod másolni. Ha pointerekkel dolgozol, vagy több ilyen változó kell, akkor meg a makróknak adhatod paraméterként a változót is.
- A hozzászóláshoz be kell jelentkezni
Menj 4 bájtra, akkor RGBA-ra is megvan a megoldás.
- A hozzászóláshoz be kell jelentkezni
+1. Nameg gyorsabb azzal dolgozni.
----------------
Lvl86 Troll
- A hozzászóláshoz be kell jelentkezni
Ez sokat dobott a sebességen, köszi! És köszönet az előző hozzászólóknak is, mert teljes mértékben igazatok van, hogy a 2**n bájtokkal könnyebben bánik a gép.
--
Azt akarom, hogy az emberek ne kényszerből tanuljanak, hanem azért, mert tudni akarnak.
- A hozzászóláshoz be kell jelentkezni
A logika egyebkent egyszeru. Minden szamitogep binaris rendszerben gondolkodik, tehat mindig ketto hatvanyaival tud a legkonnyebben dolgozni. Amint nem ketto hatvanyaival kell szamolni, egy csomo workaroundot kell tennie, igy romlik a teljesitmeny.
--
()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.
- A hozzászóláshoz be kell jelentkezni