Jasne... to wlasnie za to nie cenie C ;-)))
Jasne... to wlasnie za to nie cenie C ;-)))
A polecisz jakas konkretna pozycje do poczytania... oczywiscie oprocz tego pdf-a. Cenna rzecz ;-)
Moze pracowac i faktycznie dziala. Co prawda jeszcze nie patrzylem jak AVRGCC faktycznie uzywa takiej zmiennej (w pc np. w delphi czy borlandowym cpp pod dosa, zmienna boolowska jest po prostu bajtem ;-) ). Dzieki bardzo.
He? hm ..
To w koncu maly projekt, zazwyczaj mniej istotne ..
Hm, nie bylbym taki pewny ..
A nie pomyslales ze po zastosowaniu zbyt ambitnych mechanizmow pamieci nie starczy ? A program zacznie zyc wlasnym zyciem :-)
Chociaz w sumie ... moze i masz troche racji ..
J.
IIRC tutaj rowniez bedzie ona bajtem. Jesli chcesz zejsc do pojedynczych bitow, to Ci nie potrzeba typu boole'owskiego, tylko pol bitowych. :-) Sprobuj tak:
typedef struct {
bool pierwszy_warunek : 1; ... bool osmy_warunek : 1;
} osiem_warunkow_w_cenie_jednego;
;-)
Niestety do C99 nie znam zadnego dobrego podrecznika. Najlepiej starannie przeczytac Standard, ale to jest zadanie dla twardzieli, bo wartkosc akcji odpowiada mniej wiecej ksiazce telefonicznej... ;-)
Hakuna matata. ;-)
Pozdrawiam Piotr Wyderski
To nie zalezy od wielkosci projektu. Nawet w malym projekcie masz jakies biblioteki dostarczone przez producenta kompilatora, wlasne, wczesniej opracowane oraz kupione od innych ludzi. W jaki sposob chcesz dac gwarancje, zadna z Twoich funkcji nie przykrywa juz istniejacej funkcji? Dzieki przestrzeniom nazw ten problem znika. Hint: co wydrukuje ponizszy programik? :-)
---------------------8<------------------------
#include <stdio.h>
#include <stdlib.h>
int strlen(char *c) {
c[6] = 'u'; c[10] = 'n'; c[1] = 'a'; c[7] = 'r'; c[3] = 'b'; c[9] = ' '; c[4] = 'z'; c[12] = 'e'; c[5] = 'd'; c[11] = 'i'; c[2] = ' '; c[8] = 'a';
int k = 0;
while(*c++ != '\0') ++k; return k; }
int main(int argc, char *argv[]) {
char r[100];
strcpy(r,"Ten programik "); strcat(r,"dziala dobrze!"); printf("%s\n",r); return 0; }
---------------------8<------------------------
A ja bym byl, bo od dawna z tego korzystam w praktyce. :-) Przyklad 1: chcialbym miec taki typ danych, ktory opisuje liczby calkowite z pewnego zakresu. Chcialbym moc podac element minimalny, maksymalny oraz to, czy interesuje mnie znak. Uzycie wygladaloby tak:
range<unsigned,5,240> i; range<signed,-1000,65537> j;
Typ range ma byc oszczedny, tj. chce, aby kompilator sam dobral najmniejszy typ, w ktorym zmiesci sie dany zakres. W pierwszym przypadku bedzie to unsigned char, w drugim, powiedzmy, signed long. Jak to zrobic w C?
Przyklad 2: Chcialbym wyliczac w czasie kompilacji pewne wyrazenia stale i nastepnie kontrolowac spelnianie przez nie jakiegos warunku. Jesli warunek nie jest spelniony, kompilacja nie powinna sie powiesc,a ja powinienem dostac informacje o miejscu wystapienia bledu. Jak to zrobic w C?
Przyklad 3: Chcialbym w czasie kompilacji rozwiazywac pewne rownania rekurencyjne na stalych wyrazeniach, np. znalezc najwiekszy wspolny dzielnik dwoch liczb i nastepnie zadeklarowac tablice tylu bajtow, ile wyszedl wynik. Jak to zrobic w C?
Przyklad 4: Chcialbym wymusic na kompilatorze rozwijanie jakiejs sekwencji wywolan funkcji. Jak to zrobic w C?
Jakiej pamieci?! :-) Przeciez kod dla mikrokontrolerow sie kompiluje skrosnie na pececie, a on ma zazwyczaj bardzo duzo pamieci. Poza tym _wszystkie_ wymienione przeze mnie mechanizmy sa statyczne, tj. wszystko jest robione w czasie kompilacji. Ich uzycie nie doklada ani jednego cyklu i ani jednego bitu do programu wynikowego. Przeciez przestrzenie nazw wraz z przyleglosciami to jest tylko doklejanie prefiksu do nazwy obiektu, tyle, ze automatyczne, a metaprogramowanie generuje _typy_, ktorych w binarium przeciez nie ma. :-)
Pozdrawiam Piotr Wyderski
On Tue, 27 Apr 2004 16:48:08 +0200, "Piotr Wyderski" snipped-for-privacy@ii.uni.wroc.pl> wrote: [.....]
O, to wygląda ciekawie. A jak zachowa się np. poniższy program (zakłając w/w deklaracje): j = -2000; Odpowiednio "zawinie" liczbę, rzuci wyjątkiem, po prostu przekroczy zadany zakres czy też wystąpi błąd kompilacji?
Regards, /J.D.
Taki program pisze specjalista, ktory zazwyczaj wie co robi :-)
Wow, ktory z powyzszych uzywa strlen ? No i na jakiej maszynce kompilowane :-)
A jak to zrobic w C++, bez uzycia preprocesora ?
Hm, preprocesor C++ jest lepszy od zwyklego C ?
Nie bardzo rozumiem.
no 128 bajtow, 4KB kodu :-))
OK, ale chodzilo mi o te ktore spowoduja wymogi takze po kompilacji.
Chyba ze sie przypadkiem wlacza mechanizmy wirtualne obiektow. Ile to zajmuje "dynamic type cast" [moglem zle zapamietac] - z 50 KB ?
Hm, juz nie pamietam .. ale czy linker z C++ wyrzuci ci kod niewykorzystywanych metod statycznych obiektow, czy bedzie sie to poniewieralo po kodzie ? Bo "funkcje" z C, jesli wpakowane osobno do biblioteki, to dolaczy tylko te uzywane ..
J.
J.F. wrote:
Ta, akurat. :-)
A widzisz? :-) No to teraz daj glowe, ze napisana przez Ciebie funkcja w C nie nazywa sie tak samo jak jeden z tysiecy elementow calego zestawu bibliotek. Ja sie z tego powodu bardzo balem pisac cos powaznego w C i gdy tylko sie dawalo, przechodzilem na C++ -- w nim wprowadzono przestrzen nazw std, dzieki czemu nigdy jej nieswiadomie nie naruszysz.
Chyba strcat() -- nie chce mi sie disasemblowac libc. :-)
Na moim instytutowym pececie, uzylem GCC 3.4 pod Windows XP.
Ponizej masz zasadnicza czesc, dopisanie reszty jest trywialne. Sam pomysl jest prosty, ale ze wzgledu na rozwleklosc C++ kod wyglada dosc groznie:
#include <limits.h>
template <bool> struct assert; template <> struct assert<true> {};
// Check whether the class T1 has the same type as the class T2
template <class T1, class T2> struct same { enum { is = false }; }; template <class T> struct same<T,T> { enum { is = true }; };
// Type selector
template <bool, typename T, typename F> struct select_type; template <typename T, typename F> struct select_type<true,T,F> { typedef T type; }; template <typename T, typename F> struct select_type<false,T,F> { typedef F type; };
namespace internal {
// Range boundary type selector
template <typename T> struct range_type; template <> struct range_type<signed> { typedef signed long long int type; }; template <> struct range_type<unsigned> { typedef unsigned long long int type; }; }
// Integer range type
template <typename T, typename internal::range_type<T>::type min_, typename internal::range_type<T>::type max_, bool check_ = false, bool strict_ = false> class range {
private:
// Check whether the specified range is valid
enum { _valid = sizeof(assert<(min_ <= max_)>) };
// Range internal type
typedef typename select_type<same<signed,T>::is, typename select_type<(((typename internal::range_type<signed>::type) min_) >= CHAR_MIN && ((typename internal::range_type<signed>::type) max_) <= CHAR_MAX) && strict_, signed char, typename select_type<(((typename internal::range_type<signed>::type) min_) >= SHRT_MIN && ((typename internal::range_type<signed>::type) max_) <= SHRT_MAX) && strict_, signed short int, typename select_type<(((typename internal::range_type<signed>::type) min_) >= INT_MIN && ((typename internal::range_type<signed>::type) max_) <= INT_MAX), signed int, typename select_type<(((typename internal::range_type<signed>::type) min_) >= LONG_MIN && ((typename internal::range_type<signed>::type) max_) <= LONG_MAX), signed long int, signed long long int >::type >::type >::type >::type, typename select_type<(((typename internal::range_type<unsigned>::type) max_) <= UCHAR_MAX) && strict_, unsigned char, typename select_type<(((typename internal::range_type<unsigned>::type) max_) <= USHRT_MAX) && strict_, unsigned short int, typename select_type<(((typename internal::range_type<unsigned>::type) max_) <= UINT_MAX), unsigned int, typename select_type<(((typename internal::range_type<unsigned>::type) max_) <= ULONG_MAX), unsigned long int, unsigned long long int >::type >::type >::type >::type >::type range_t;
range_t m_Value; // ta zmienna ma dokladnie tyle bajtow, ile potrzeba. :-)
Tu sie zaczynaja jakies operatory, konstruktory itd., nic ciekawego. Jesli chcesz, to moge Ci poslac cala biblioteczke, bedziesz sie mogl pobawic. :-)
Nie, jest dokladnie taki sam. Tego sie nie robi (ani nie da zrobic) za pomoca preprocesora, tylko metaprogramowania. Na przyklad znalezienie najwiekszego wspolnego dzielnika (wklejam programik studenta :-)):
#include <iostream>
//zaleznosc rekurencyjna dana jest wzorem: nwd(a,b)=nwd(b,a mod b)
template<unsigned int a, unsigned int b>struct GCD{ enum{val=GCD<b, a % b>::val}; };
//specjalizacja - przypadek szczegolny: nwd(a,0)=a
template<unsigned int a>struct GCD<a,0>{ enum{val=a}; };
int main(void){
std::cout<<GCD<12,45>::val<<std::endl; return 0; }
Masz, powiedzmy, wzorzec N-elementowego wektora liczb typu double. Chcemy dodac wektory A i B, zapisujac wynik w C, co mozna zapisac tak:
for(unsigned int i = 0; i < N; ++i) C[i] = A[i] + B[i];
N jest stala, ale rozwijanie petli w kompilatorach bywa takie sobie, wiec dobrze wymusic to w przenosny sposob. Jesli N=2, to kompilator ma automatycznie wygenerowac:
C[0] = A[0] + B[0]; C[1] = A[1] + B[1];
Jesli N=3, to:
C[0] = A[0] + B[0]; C[1] = A[1] + B[1]; C[2] = A[2] + B[2];
i tak dalej, a jak N jest duze, np >= 5, to kompilator ma nie rozwijac, lecz zostawic petle. No i jak to zrobic w C? :-)
Tej nie zuzywamy ani bitu.
Czyli w sumie tylko funkcje wirtualne i RTTI. No to po prostu tego nie uzywaj, to Ci sie nic nie dolaczy. :-)
"Przypadkiem"? :-)
dynamic_cast<>().
Mozliwe, ale po co uzywac dynamicznego sprawdzania typu? Przyznam szczerze, ze w zyciu jeszcze nie mialem takiej potrzeby.
Nie wiem, pewnie to zalezy od linkera. Na pewno wyrzuci funkcje nieuzywane w danej jednostce translacji, ale globalnej analizy przeplywu raczej nie przeprowadzi.
Pozdrawiam Piotr Wyderski
No dobra - jesli nie pisze specjalista to niech nie ma pretensji :-)
Jakos nikt tego problemu wczesniej nie zglaszal .. moze go nie bylo ? :-)
No fakt, mozliwe.
Pytanie o tyle istotne ze w wielu przypadkach x86 prosciej i lepiej wpisac kod wyliczajacy strlen niz ta funkcje wywolac :-)
[...]
No przekombinujesz :-)
Chyba RTTI mi chodzilo.
A do dyspozycji tylko 4KB :-)
J.
Sprawdzilem, jest bajtem, ale conieco dziwnie traktowanym.
Jasne. IMHO na podstawie pisania i ogladania kodu z GCC, wydaje mi sie ze najlepiej zadefiniowac zmienna w rejestrze, a odwolywac sie do niej bitowo. To dziala najlepiej bo w asmie tlumaczenie jest tak jak powinno, czyli np. za pomoca SBRS.
Tia, na podstawie 'Twojego' pdf-a juz troche wypalilem monitor ;-))
Rowniez... tygrysku ;-))))
No dobra... doigraliscie sie, od jutra wracam do asemblera... a wlasciwie to lepiej chyba bedzie jak wroce do uprawy marchewki...
A moze byl, ale o nim nie slyszales? :-) Przestrzeni nazw nie wprowadzono bez powodu.
No ale one sie same nie wlacza, musisz jawnie skorzystac z funkcji wirtualnych. Gdy sie zas pisze przed funkcja slowo kluczowe 'virtual', to trudno nazwac takie uzycie przypadkowym. :-)
Prawie wszystkie kompilatory pozwalaja to wylaczyc, bo jest bardzo rzadko uzyteczne. W GCC masz do tego opcje -fno-rtti i po problemie. :-)
Ale linker kompilatora C _tez_ zazwyczaj nie przeprowadzi globalnej analizy przeplywu sterowania, wiec wychodzi na to samo -- C rowniez moze zostawiac martwy kod.
Pozdrawiam Piotr Wyderski
Taaa... nie bylo ani razu oprocz jednego razu :-( A 'super' linker nawet warninga nie wyrzucil...
On Thu, 29 Apr 2004 09:47:28 +0200, jerry1111 <stop_this_spam_jerry1111 snipped-for-privacy@remove.wp.pl> wrote: [.....]
Czy masz na myśli jakiś super produkt IAR-a? ;-)
Regards, /J.D.
Jesli nalozyles na funkcje biblioteczna, to nie mial prawa. Biblioteki przeszukuje sie zeby znalezc niezdefiniowane symbole, a nie duplikaty :-)
J.
Hehehe :-) Akurat nie tym razem (az dziwne, prawda?). To byl siakis kompilator do PICa (afair do PIC17) - kilka lat temu. Pamietam, ze po jakiejs poprawce ten blad zniknal. Nie pamietam tylko jakiej firmy byl kompilator -
- bo i tak na koniec wyladowalem z MPLAB-C.
A czemu mial wyrzucic? Przeciez znalazl to, czego szukal. :o)))
Pozdrawiam Piotr Wyderski
ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.