Zkopírování části paměti - memcpy – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Zkopírování části paměti - memcpy – C / C++ – Fórum – Programujte.comZkopírování části paměti - memcpy – C / C++ – Fórum – Programujte.com

 

Toto vlákno bylo označeno za vyřešené.
oxidián0
Grafoman
7. 8. 2017   #1
-
0
-


LSB je int. buf je char *. Potřebuji do buf nakopírovat 4 byty z LSB (z leva doprava). Zkouším dvě možnosti:
 

1)
buf[0] |= LSB & 0xFF000000;
buf[1] |= LSB & 0x00FF0000;
buf[2] |= LSB & 0x0000FF00;
buf[3] |= LSB & 0x000000FF;
nic to nedělá
2)
memcpy(buf, (int) &LSB, 4); // přepiš 3 byty od konce

taky nic to nedělá


buf: 0x22e864 "Aenean."

LSB: 196611


Když vymažu operátor & u memcopy tak mám hlášení: makes pointer from integer without a cast [enabled by default]| include\string.h|38|note: expected 'const void *' but argument is of type 'int'| Přímo LSB jako source tam dát nemohu, to by krachlo. Co s tím?
 

Nahlásit jako SPAM
IP: 78.102.61.–
KIIV
~ Moderátor
+43
God of flame
7. 8. 2017   #2
-
0
-

#1 oxidián

varianta jedna nic nekopiruje (operator |= neni kopie), krom toho se ti vysledek u 3 ze 4 osekne na jeden byte, takze vzdy budes delat or s 0 coz je puvodni hodnota. Nejmene u toho na indexu 3 bych cekal mensi zmenu.

Varianta dve by mohla i fungovat, ale bude zalezet na byte orderu. Na vetsine oblibenych procesoru bude prvni LSB (little endian). A podle prvni varianty hadam, ze to bude presne obracene.

Nahlásit jako SPAM
IP: 217.196.214.–
Program vždy dělá to co naprogramujete, ne to co chcete...
oxidián0
Grafoman
7. 8. 2017   #3
-
0
-

Operace mecpy ale ani nevymaže ty data, takže se nekopíruje nic. Ten původní řetězec zůstal nedotčený.
 

Ani toto nedělá změnu:

buf[0] |= LSB & 0xFF000000 ;
buf[1] |= LSB & 0x00FF0000 << 8;
buf[2] |= LSB & 0x0000FF00 << 16;
buf[3] |= LSB & 0x000000FF << 24;
Nahlásit jako SPAM
IP: 78.102.61.–
KIIV
~ Moderátor
+43
God of flame
7. 8. 2017   #4
-
+1
-
Zajímavé

#3 oxidián
 

#include <stdio.h>
#include <string.h>

int main() 
{
	unsigned char  buf[] = "Aenenan";
	unsigned int   lsb   = 196611;

	for (int i=0; i<7; ++i) printf("%d '%c';", buf[i], buf[i]);
	printf("\n");

	memcpy(buf, &lsb, 4);

	for (int i=0; i<7; ++i) printf("%d '%c';", buf[i], buf[i]);
	printf("\n");
}

Vysledek:

./a.out 
65 'A';101 'e';110 'n';101 'e';110 'n';97 'a';110 'n';
3 '';0 '';3 '';0 '';110 'n';97 'a';110 'n';

Takze evidentne funguje.

Taktez to same vyflusne:

*((unsigned int*)buf) = lsb;

Pokud bys to chtel v opacnem poradi, tak nejake funkce pro endianitu z <endian.h>.

A pak je jeste spousta dalsich moznosti:

    buf[0] = lsb >> 24;
    buf[1] = lsb >> 16;
    buf[2] = lsb >> 8;
    buf[3] = lsb;

To uz vyflusne:

0 '';3 '';0 '';3 '';110 'n';97 'a';110 'n';
Nahlásit jako SPAM
IP: 217.196.214.–
Program vždy dělá to co naprogramujete, ne to co chcete...
oxidián0
Grafoman
7. 8. 2017   #5
-
0
-

Já už vím co mám špatně (částečně). Já nemám pracovat přímo s buf ale s pointerem s ukazujícím na buf

char * s, *pEnd, *pStart, *pMSB2start, *pLSB16start;
pEnd = buf + bufLen - 1; // pEnd is +1B out of buffer!
pMSB2start = pEnd;
pLSB16start = pEnd - 3; // -3B ; 2b * 12 = 24b = 3B
s = pLSB16start;

...

s -= 4; // set pointer

memcpy(s, &LSB, 4);

s before: 0x22e864 "Aenean."

s after: 0x22e864 "�03"

// s: 0x22e864 "Aenean."
s[0] = LSB << 24;
s[1] = LSB << 16;
s[2] = LSB << 8;
s[3] = LSB;

můj výsledek:

s[0] = \000

s[1] = \000

s[2] = \000

s[2] = \003

což vypadá že se někam vytratili ty dvě binární 11 na začátku (zleva) LSB

tak asi ten kod není dobře

ale toto funguje:

*((unsigned int*)s) = LSB;


výsledek:

3 '\003'
0 '\000'
3 '\003'
0 '\000'
Nahlásit jako SPAM
IP: 78.102.61.–
oxidián0
Grafoman
7. 8. 2017   #6
-
0
-

Ještě potřebuju vyřešit jednu věc s tím LSB,

m[i] = 0b000000110000000000000011; // 196609

m[i+1] = 0b000000110000000000000011; // 196609
LSB = 0;
LSB |= m[i] & ~0xFFFF0000 << 16; // 16 bits LSB
LSB <<= 16;
LSB |= m[i+1] & ~0xFFFF0000; // tady se má zkopírovat jen 2 byty zprava, aby se nepřepsalo to co jsem zkopíroval a posunul výše.

Jak opravit ten poslední řádek aby se zkopírovaly jen 2 byty neboli 16bitů? Jde o to zachovat 16 bitů MSB a zkopírovat tam 16 bitů zprava.

Pro tom prvním posunu se z čísla 3 stane binárně

11000000 00000000 00

a po druhém nakopírování by tam mělo být

11000000 00000000 11

teda správně rozděleno by to bylo takto:

   |-> dalších 16 bitů

11 00000000 00000000

11 00000000 00000011
Nahlásit jako SPAM
IP: 78.102.61.–
KIIV
~ Moderátor
+43
God of flame
7. 8. 2017   #7
-
0
-

#6 oxidián
na to, aby se ti dalo odpovedet, bych musel vedet, jakeho typu jsou m, LSB.

Proc napriklad delas  ~0xFFFF0000, kdyz rovnou muzes zapsat 0xFFFF (respektive 0xFFFFU, aby to bylo bez znamenka). No a kdyz to pak jeste posunes o 16, tak vlastne zbyde zase  0xFFFF0000. No a tim pak vymaskujes to m[i].

// priklad:

unsigned int  val =  0xDEADBEEFU;

printf("0x%08x\n", (val & ~0xFFFF0000U) << 16); // prints: 0xbeef0000
printf("0x%08x\n", val & ~0xFFFF0000U << 16);   // prints: 0xdead0000
Nahlásit jako SPAM
IP: 37.188.252.–
Program vždy dělá to co naprogramujete, ne to co chcete...
oxidián0
Grafoman
7. 8. 2017   #8
-
0
-

unsigned int m[12];

unsigned int LSB = 0;

Tak asi to má být takto:

LSB = 0;
LSB |= m[i] & 0xFFFFU << 16; // 16 bits LSB
LSB |= m[i+1] & 0xFFFFU;

A hle, ono to funguje! Tak dík.

Druhý řádek nastaví LSB: 196608

třetí řádek LSB: 196611

A dále v kódu pak s je:

s[0] = 3 '\003'

s[1] = 0 '\000'

s[2] = 3 '\003'

s[3] = 0 '\000'
Nahlásit jako SPAM
IP: 78.102.61.–
KIIV
~ Moderátor
+43
God of flame
7. 8. 2017   #9
-
0
-

#8 oxidián
 

LSB  = m[i] & 0xFFFF0000u; // to je to co tam ted mas na druhem radku
LSB |= m[i+1] & 0xFFFFu;   // urcite neprepise nic nad 16. bit, jelikoz se tam nemuze vyskytnout zadna logicka jednicka.
Nahlásit jako SPAM
IP: 37.188.252.–
Program vždy dělá to co naprogramujete, ne to co chcete...
oxidián0
Grafoman
7. 8. 2017   #10
-
0
-

#9 KIIV
"m[i+1] & 0xFFFFu; // urcite neprepise nic nad 16. bit, jelikoz se tam nemuze vyskytnout zadna logicka jednicka"

OK. To dává smysl. Takže když říkáš "nad 16. bit" to tedy v programátorské hantýrce znamená směrem od LSB k MSB, chápu to správně?

Nahlásit jako SPAM
IP: 78.102.61.–
KIIV
~ Moderátor
+43
God of flame
7. 8. 2017   #11
-
0
-

#10 oxidián
LSB je nejmene platny bit s vahou 2^0 = 1 (je to klasicka pozicni soustava). Dalsi bit ma pozici 1, tj. 2^1 = 2

Pokud chces vedet dekadickou hosnotu nejakeho cisla, tak to funguje nasledovne:

0b1000101 =>  1 * 2^6  +  0 * 2^5  +  0 * 2^4  +  0 * 2^3  +  1 * 2^2  +  0 * 2^1  +  1 * 2^0 => 64 + 4 + 1 = 69

Jak jsi asi pochopil, tak se v pozicnich soustavach pocitaji pozice od desetinne carky (z prava do leva), za desetinnou carkou jsou pak zaporne.  0b0,1  by pak bylo:  1 * 2^(-1)   =   0.5 dekadicky

Nahlásit jako SPAM
IP: 37.188.252.–
Program vždy dělá to co naprogramujete, ne to co chcete...
oxidián0
Grafoman
7. 8. 2017   #12
-
0
-

A tak jo, já jsem se to kdysi učil ty různé soustavy a rozebírání čísel. Myslím že jsem to ještě nezapomněl.

Nahlásit jako SPAM
IP: 78.102.61.–
KIIV
~ Moderátor
+43
God of flame
7. 8. 2017   #13
-
0
-

#12 oxidián
ja jen proc je to v programatorske hantyrce od LSB po MSB. Podobne muzu vysvetlit or a and, booleovy zakony, ...

Nahlásit jako SPAM
IP: 37.188.252.–
Program vždy dělá to co naprogramujete, ne to co chcete...
oxidián0
Grafoman
7. 8. 2017   #14
-
0
-

Radši ne. Dík. Já se to kdysi učil, ale paměť to víš, časem se to vykouří jak to člověk málo používá nebo nepoužívá.

Nahlásit jako SPAM
IP: 78.102.61.–
8. 8. 2017   #15
-
0
-

memcpy(buf, (int) &LSB, 4); // přepiš 3 byty od konce

šílenej guláš. Získáš ukazatel, ten přetypuješ na int a cpeš ho jako parametr funkci memcpy, která chce ukazatel. Navíc podle třetího parametru memcpy se kopírují 4 Byty.

Nebylo by od věci rozepsat si všechno do jednotlivých řádků a krokovat v debuggeru a dívat se na hodnoty proměnných.

Pochybuji, že by z tebe mohl být alespoň průměrný lepič kódu (jako jsem já) když ses do teď nenaučil ani základní věci probírané v kdejakém tutoriálu. Za dobu, kterou sem na fórum chodíš, jsem dokázal sestavit "woknovou" aplikaci, která četla z COMu, zobrazovala průběžně hodnoty a ukládala je do souboru. Nebylo to kdovíjak učesané, ale fungovalo to spolehlivě. Co vše umí WinAPI nebo co je objektové programování jsem ještě nevěděl, ale používání datových typů a ukazatelů jsem znal.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
oxidián0
Grafoman
8. 8. 2017   #16
-
0
-

Jsou to tvoje pochyby ne moje. Za dobu co jsem chodím jsem se věnoval třem, respektive čtyřem jazykům. Céčko jsem skoro úplně zapomněl, takže je to jako bych začal právě teď.  Ale neboj já si zase rozpomenu.

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

Podobná vlákna

Memcpy(); a std::string — založil Figa

Zkopírování hry — založil xp

Zkopírování souboru — založil Petr

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ý