Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

#ActualHodgman

Posted 29 March 2012 - 08:18 AM

A problem I met is that, I have been used to use STL data structure such as vector for a long time, but C doesn't have STL. I tried to write some general data structure like linked list, using function pointers to apply general operations. But soon I found it's not so easy to be general. So I want to know how does professional C programmer write their daily codes? For example, when a linked list is used to organize some data, will you directly operate the pointer to next node in the application's algorithm, or will make an abstraction to hide the details of linked list?

I'm in the opposite situation where I'm writing C-style code and data-structures in C++, because simple C-inspired structures have a lot of benefits over C++-style structures like the STL collections...[source lang=cpp]template<class T> struct Offset{    const T* Ptr() const { return (T*)(((u8*)&offset) + offset); }          T* Ptr()       { return (T*)(((u8*)&offset) + offset); }    const T* operator->() const { return Ptr(); }          T* operator->()       { return Ptr(); }    const T& operator *() const { return *Ptr(); }          T& operator *()       { return *Ptr(); }    uint DataSize() const { return sizeof(T); }private:    s32 offset;};template<class T> struct Array{    const T* Ptr() const { return (T*)(((u8*)&offset) + offset); }          T* Ptr()       { return (T*)(((u8*)&offset) + offset); }    const T& operator *() const { return *Ptr(); }          T& operator *()       { return *Ptr(); }    const T& operator[](uint i) const { return Ptr()[i]; }          T& operator[](uint i)       { return Ptr()[i]; }    uint DataSize(uint count) const { return sizeof(T) * count; }private:    s32 offset;};template<class T> struct Address{    const T* Ptr(const void* base) const { return (T*)(((u8*)base) + offset); }          T* Ptr(const void* base)       { return (T*)(((u8*)base) + offset); }    uint DataSize() const { return sizeof(T); }private:    u32 offset;};template<class T> struct List{    u32 Count() const { return count; }    const T* Begin() const { return (T*)(&count + 1); }          T* Begin()       { return (T*)(&count + 1); }    const T* End  () const { return Begin()+count; }          T* End  ()       { return Begin()+count; }    const T& operator[](uint i) const { eiASSERT(i < count); return Begin()[i]; }          T& operator[](uint i)       { eiASSERT(i < count); return Begin()[i]; }    uint DataSize() const { return sizeof(T) * count; }private:    u32 count;};struct String { u8 length; u8 chars; };struct StringOffset{    bool operator==( const StringOffset& other )    {        const String& a = *this->Ptr();        const String& b = *other.Ptr();        return unlikely(&a==&b) || ( unlikely((offset&~0xFFFFU)==(other.offset&~0xFFFFU))                                     && likely(a.length==b.length)                                     && likely(0==memcmp(&a.chars, &b.chars, a.length)) );    }    const String* Ptr() const { return (String*)(((u8*)&offset) + (offset&0xFFFFU)); }          String* Ptr()       { return (String*)(((u8*)&offset) + (offset&0xFFFFU)); }    const String* operator->() const { return Ptr(); }          String* operator->()       { return Ptr(); }    const String& operator *() const { return *Ptr(); }          String& operator *()       { return *Ptr(); }private:    s32 offset;};[/source]

#1Hodgman

Posted 29 March 2012 - 08:15 AM

A problem I met is that, I have been used to use STL data structure such as vector for a long time, but C doesn't have STL. I tried to write some general data structure like linked list, using function pointers to apply general operations. But soon I found it's not so easy to be general. So I want to know how does professional C programmer write their daily codes? For example, when a linked list is used to organize some data, will you directly operate the pointer to next node in the application's algorithm, or will make an abstraction to hide the details of linked list?

I'm in the opposite situation where I'm writing C-style code and data-structures in C++:[source lang=cpp]template<class T> struct Offset{    const T* Ptr() const { return (T*)(((u8*)&offset) + offset); }          T* Ptr()       { return (T*)(((u8*)&offset) + offset); }    const T* operator->() const { return Ptr(); }          T* operator->()       { return Ptr(); }    const T& operator *() const { return *Ptr(); }          T& operator *()       { return *Ptr(); }    uint DataSize() const { return sizeof(T); }private:    s32 offset;};template<class T> struct Array{    const T* Ptr() const { return (T*)(((u8*)&offset) + offset); }          T* Ptr()       { return (T*)(((u8*)&offset) + offset); }    const T& operator *() const { return *Ptr(); }          T& operator *()       { return *Ptr(); }    const T& operator[](uint i) const { return Ptr()[i]; }          T& operator[](uint i)       { return Ptr()[i]; }    uint DataSize(uint count) const { return sizeof(T) * count; }private:    s32 offset;};template<class T> struct Address{    const T* Ptr(const void* base) const { return (T*)(((u8*)base) + offset); }          T* Ptr(const void* base)       { return (T*)(((u8*)base) + offset); }    uint DataSize() const { return sizeof(T); }private:    u32 offset;};template<class T> struct List{    u32 Count() const { return count; }    const T* Begin() const { return (T*)(&count + 1); }          T* Begin()       { return (T*)(&count + 1); }    const T* End  () const { return Begin()+count; }          T* End  ()       { return Begin()+count; }    const T& operator[](uint i) const { eiASSERT(i < count); return Begin()[i]; }          T& operator[](uint i)       { eiASSERT(i < count); return Begin()[i]; }    uint DataSize() const { return sizeof(T) * count; }private:    u32 count;};struct String { u8 length; u8 chars; };struct StringOffset{    bool operator==( const StringOffset& other )    {        const String& a = *this->Ptr();        const String& b = *other.Ptr();        return unlikely(&a==&b) || ( unlikely((offset&~0xFFFFU)==(other.offset&~0xFFFFU))                                     && likely(a.length==b.length)                                     && likely(0==memcmp(&a.chars, &b.chars, a.length)) );    }    const String* Ptr() const { return (String*)(((u8*)&offset) + (offset&0xFFFFU)); }          String* Ptr()       { return (String*)(((u8*)&offset) + (offset&0xFFFFU)); }    const String* operator->() const { return Ptr(); }          String* operator->()       { return Ptr(); }    const String& operator *() const { return *Ptr(); }          String& operator *()       { return *Ptr(); }private:    s32 offset;};[/source]

PARTNERS