konto usunięte

Temat: Pytanie

Witam

Mam pytanie odnośnie implementacji, muszę włożyć
struct { cos cos1: costam costam2; }
w
insigned char * buffor;
Mam do napisania ramkę protokołu który na sztywno ma struct a gość wymyślił sobie super symulator (który nie można zmienić) i musze to władować w buffor.

Jako iż mało pracowałem z c++, proszę o pomoc.
Czy jest to w ogóle możliwe?
Jeśli bezpośrednio tak to kamień z serca, jeśli nie jest jakiś sposób ?
Jakub L.

Jakub L. Programista

Temat: Pytanie

bufor = new unsigned char[sizeof(ramka)];
memcpy(bufor, &ramka, sizeof(ramka));
może.
Ale może zależeć to od cosiów w strukturze.Jakub L. edytował(a) ten post dnia 18.12.09 o godzinie 23:01

konto usunięte

Temat: Pytanie

wybacz nie ogarnięty jestem o tej porze

struct ramka
{
cos cos2;
costam costam2;
};

zmieni to to co wypisales?

cos i costam to też struct'ura
czyli
struct cos
{
int size;
nastepnycos cos123; <- też struktura
};Robert Gałus edytował(a) ten post dnia 18.12.09 o godzinie 23:06
Łukasz C.

Łukasz C. Senior Technical
Architect

Temat: Pytanie

struktura w strukturze nie jest wskaznikiem wiec tak jak napisal Jakub powinno dzialac, chociaz sprawdz jakie wielkosci maja poszczegolne zagniezdzone struktory, bo jest cos takiego jak aligning - moze sie zdarzyc ze bedziesz mial "puste" bajty, ktore zmieniaja offsety do danych podstruktur, ale pewny w tym przypadku nei jestem

przyklad tego o czym pisze:

#include <stdio.h>

// 4 + 5 + 1 + 1 = 11
struct S1
{
int a;
char xxx[5];
char b;
char c;
};

// 7 + 4 + 1 + 1 = 13
struct S2
{
char xxx[7];
int y;
char a;
char b;
};

struct S3
{
struct S1 s1;
struct S2 s2;
};

int main()
{
struct S3 s3;
unsigned long p1, p2;

printf("%lu\n", sizeof (struct S1));
printf("%lu\n", sizeof (struct S2));
printf("%lu\n", sizeof (struct S3));

printf("%lu\n", sizeof (s3));
printf("%lu\n", sizeof (s3.s1));
printf("%lu\n", sizeof (s3.s2));

p1 = (unsigned long)&s3.s1;
p2 = (unsigned long)&s3.s2;
printf("%lu\n", p2 - p1);

return 0;
}

wyniki:
[cepa@szatan:~] # ./test
12
16
28
28
12
16
12

wniosek: aligning do wielokrotnosci 4 bajtow :)Łukasz Cepowski edytował(a) ten post dnia 19.12.09 o godzinie 09:55

konto usunięte

Temat: Pytanie

mogę się nap dowoływać tak

ramka.podramka.bajtAA=1234; ??
Jakub L.

Jakub L. Programista

Temat: Pytanie

Zaczyna misię widzieć, że to nie jest widzimisie dyrektora, tylko prowadzącego zajęcia.Jakub L. edytował(a) ten post dnia 19.12.09 o godzinie 19:37
Szymon Kubisiak

Szymon Kubisiak Developer aplikacji
mobilnych Android

Temat: Pytanie

Definiując strukturę, która będzie zapisywana binarnie (a o tym mówimy) trzeba jej definicję poprzedzić #pragma pack 1 (a potem przywrócić odpowiednie pakowanie!).

Czyli w tym przypadku zarówno 'cos', 'costam' jak i 'ramka', wszystko opakować #pragma pack, oraz oczywiście używać wyłącznie zmiennych o stałej wielkości, np char, lub __int64, nigdy int który miewa różną wielkość na różnych maszynach.

Nie wiem jak z przenośnością #pragma pack, na MSVC działa doskonale. Rzuć też okiem na align.

Tzn to jest podejście w stylu C, zorganizować pamięć tak by dało się ją zapisać jednym rzutem.

Drugie podejście to w stylu C++ lub też języków wysokopoziomowych.
Każdej strukturze dodajesz metody typu Serialize(unsigned char* aBuf, int aBufferSize) i Deserialize(unsigned char* aBuf, int aBufferSize).
Wtedy strukturka sobie ładnie zapisuje (wczytuje) swoje proste dane, bajt po bajcie, ze wszysktimi konwersjami, zmianami endianess itd a następnie każe się tak samo zapisać swoim memberom które same są skomplikowanymi klasami/strukturami.

Podejście pierwsze jest super szybkie w zapisie i odczycie, niestety w działaniu _może_ być wolne. Po to są packi i aligny by dane leżały na wygodnych dla procesora miejscach, jak je upakujesz bez odstępów to sięganie do nich _może być_ bardziej skomplikowane.
No i jak jest tam jakikolwiek pointer, to już nie działa.

Podejście drugie jest wolne w zapisie i odczycie, za to ma praktycznie nieograniczoną elastyczność, umożliwia współpracę zupełnie różnych maszyn, (np big-endian ze small), zapisywanie tylko istotnych danych a odrzucanie śmieci a także zapisywanie memberów przechowywanych jako pointery, także polimorficznych.

Moja rada - jeśli to co piszesz służy do komunikacji pomiędzy takimi samymi maszynami, to zlej wszystko i zapisz jak Jakub napisał na początku. Wszystkie dane i dziury będą ułożone tak samo, więc trafią z powrotem w te same miejsca.Szymon Kubisiak edytował(a) ten post dnia 21.12.09 o godzinie 11:45

konto usunięte

Temat: Pytanie

zastanawiałem się nad bajtami typu __int8 ale nie znalazłem dokumentacji w której zrozumiałbym działanie i konwersje tego typu.
No myślę że wystarczy mi memcpy i mam nadzieje że przy testach się nie popłacze :P

konto usunięte

Temat: Pytanie

...albo można wykorzystać boost::variant, zdefiniować k typów których będziesz używał i piszesz serializację raz dla wszystkich aktualnych i przyszłych struktur...
Szymon Kubisiak

Szymon Kubisiak Developer aplikacji
mobilnych Android

Temat: Pytanie

Jeżeli używasz MSVC to tako rzecze mikrosoft :
The types __int8, __int16, and __int32 are synonyms for the ANSI types that have the same size, and are useful for writing portable code that behaves identically across multiple platforms. The __int8 data type is synonymous with type char, __int16 is synonymous with type short, and __int32 is synonymous with type int. The __int64 type has no ANSI equivalent.

http://msdn.microsoft.com/en-us/library/29dh1w7z%28VS....Szymon Kubisiak edytował(a) ten post dnia 21.12.09 o godzinie 12:28
Łukasz C.

Łukasz C. Senior Technical
Architect

Temat: Pytanie

w c99 masz naglowek, stdint.h, masz tam zadeklarowane typy o stalej dlugosci, jak int8_t, uint8_t, 16, 32, 64...

konto usunięte

Temat: Pytanie

czym się różni char od __int8 ?
Szymon widziałem już to, ale więcej przykładów nie znalazłem z wykorzystaniem tego i zrezygnowałem. Zawsze mogę zrobić int i wpisywać hex'y :)

mam nadzieję że jak będę się odwoływał tak cos.cos1.A=101; i if(cos.cos1.A=101) to mi nie narobi głupot :) ?
oczywiście przy metodzie kopiowania do bufora dostaje bufor.cos1.A=101 ??
Łukasz C.

Łukasz C. Senior Technical
Architect

Temat: Pytanie

Robert Gałus:
czym się różni char od __int8 ?
Szymon widziałem już to, ale więcej przykładów nie znalazłem z wykorzystaniem tego i zrezygnowałem. Zawsze mogę zrobić int i wpisywać hex'y :)
char = int8
unsigned char = uint8
mam nadzieję że jak będę się odwoływał tak cos.cos1.A=101; i if(cos.cos1.A=101) to mi nie narobi głupot :) ?
oczywiście przy metodzie kopiowania do bufora dostaje bufor.cos1.A=101 ??
nie narobi glupot, ogolnie wartosc danej zmiennej = jakas liczba % (2 ^ dlugosc pola w bitach).
btw jezeli masz to przesylac jako unsigned char i pozbyc sie dziwnego rzutowania itp mozesz wykorzystac unie
Tomasz Kaczanowski

Tomasz Kaczanowski Ot, programista

Temat: Pytanie

Łukasz Cepowski:
Robert Gałus:
czym się różni char od __int8 ?
Szymon widziałem już to, ale więcej przykładów nie znalazłem z wykorzystaniem tego i zrezygnowałem. Zawsze mogę zrobić int i wpisywać hex'y :)
char = int8
unsigned char = uint8

A z char nie jest to zależne od ustawień kompilatora?

signed char = int8
unsigned char = uint8

char - w zależności od ustawień?
Łukasz C.

Łukasz C. Senior Technical
Architect

Temat: Pytanie

Tomasz Kaczanowski:
A z char nie jest to zależne od ustawień kompilatora?
a tego niewiem, jedynie slyszalem ze wielkosc char nie koniecznie musi wynosci 8bitow moze byc wieksza...
Szymon Kubisiak

Szymon Kubisiak Developer aplikacji
mobilnych Android

Temat: Pytanie

Robert Gałus:
czym się różni char od __int8 ?

Niczym. :)

mam nadzieję że jak będę się odwoływał tak cos.cos1.A=101; i if(cos.cos1.A=101) to mi nie narobi głupot :) ?
oczywiście przy metodzie kopiowania do bufora dostaje bufor.cos1.A=101 ??

Nie ma żadnych problemów. Zawsze możesz zrobić po prostu wiekszyint = mniejszyint. Jak zrobisz w drugą stronę, dostaniesz warning - oczywiście tylko Ty możesz powiedzieć czy to ważne czy do olania (bo np masz tam wartości od 0 do 200).

Tak naprawdę wielkość inta ma znaczenie największe dopiero wtedy jak robisz memcpy - a to też liczy się to, by dane ze zmiennej o wielkości X trafiły do drugiej, dokładnie ani większej ani mniejszej.

Po skopiowaniu memcpy struktury do bufora (unsigned char*) nie ma w tym buforze już żadnych cos ani cosinnych. Teraz to tylko kupa bajtów jeden za drugim, nie wiadomo co do czego. Dopiero program po drugiej stronie robiąc memcpy z tego bufora do nowej struktury spowoduje że wskoczą one na stare miejsca, znów stając się intami, floatami czy znakami.

konto usunięte

Temat: Pytanie

@Autor wątku:

Stosowanie jakiegokolwiek typu w C/C++ w strukturze i przesyłanie tego potem jako (char *) to kiepski pomysł, bo:
- wyrównanie
- znak liczby
- rozmiar pól (rozmiar pola "char" to nie zawsze 8 bitów, co najmniej 8 bitów)
- struktura float-a
- porządek bajtów w słowie
- kodowanie znaków (char charowi nie równy - patrz EBCDIC, utf-8 na Linux...)
- obsługa intów >= 64 bity

Przesyłanie binarne bufora ze strukturą ma tylko sens przy takich samych maszynach.

Zobacz jeszcze: Protocol buffers

http://home.att.net/~jackklein/c/inttypes.html
Tomasz Kaczanowski

Tomasz Kaczanowski Ot, programista

Temat: Pytanie

Łukasz Cepowski:
Tomasz Kaczanowski:
A z char nie jest to zależne od ustawień kompilatora?
a tego niewiem, jedynie slyszalem ze wielkosc char nie koniecznie musi wynosci 8bitow moze byc wieksza...

To pamiętam należało to pilnować w starszych kompilatorach, nie wiem co mówią na ten temat najnowsze standardy, nie zwracałem na to uwagi, po prostu wtedy, gdy chce miec pewność posiadania char ze znakiem bądź bez, używam signed albo unsigned, ponieważ wcześnie było to zależne od ustawaień w kompilatorze.
Jarek Karciarz

Jarek Karciarz właściciel, OSITRON
Polska

Temat: Pytanie

Również nie polecam memcpy(). Mogą wystapić bajty z zerem binarnym, który jak wiadomo oznacza koniec łańcucha. Wtedy twoje dane zostaną obcięte. Chyba, ze osobno podasz długość całego bufora, wtedy #pragma pack załatwi sprawę.
Ogólnie, jesli chcesz przenosić struktury na tekst i odwrotnie, to dla każdego typu danych występującego w strukturze, musisz dostarczyć funkcję konwertującą dany typ na tekst i odwrotnie. Wtedy będziesz mógł przenosić pomiędzy róznymi maszynami i systemami. To nie jest trywialne zadanie i mocno zależy od costam costam. Myślę, że pomysłodawcy nie chodziło o zwykłe memcpy, bo wtedy wystarczy użyć #pragma, podac adres i rozmiar struktury i adres rzutować ze struct * na char*. Na pewno nie o to chodziło.
Łukasz C.

Łukasz C. Senior Technical
Architect

Temat: Pytanie

Jarek Karciarz:
Również nie polecam memcpy(). Mogą wystapić bajty z zerem binarnym, który jak wiadomo oznacza koniec łańcucha. Wtedy twoje dane zostaną obcięte. Chyba, ze osobno podasz długość całego bufora, wtedy #pragma pack załatwi sprawę.
memcpy,strncpy jest odporne na null terminator, strcpy faktycznie skopiuje wszystko do nulla
Ogólnie, jesli chcesz przenosić struktury na tekst i odwrotnie, to dla każdego typu danych występującego w strukturze, musisz dostarczyć funkcję konwertującą dany typ na tekst i odwrotnie. Wtedy będziesz mógł przenosić pomiędzy róznymi maszynami i systemami. To nie jest trywialne zadanie i mocno zależy od costam costam. Myślę, że pomysłodawcy nie chodziło o zwykłe memcpy, bo wtedy wystarczy użyć #pragma, podac adres i rozmiar struktury i adres rzutować ze struct * na char*. Na pewno nie o to chodziło.
imho poto wymyslili webservices, xml, soap, json itp itd

Następna dyskusja:

(virtual?) vector - pytanie.




Wyślij zaproszenie do