[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

We should not access memory address directly to read the value.

For example,

Int8* pt;
malloc(pData, 6);
pt = pData;
*pt = length;
pt++;
*pt = width;
pt++
*pt = (int)size; // ---(*)

This may create unexpected result due to data align. See (*). At (*), address of 'pt' is not 4-byte-aligned. But, it tries to write 4-byte-data (integer value). In this case, result may be compiler or target architecture dependent - usually, 'size' will be written at 4-byte-aligned-address.
Programmer who wrote above code may intent to make following memory state.

pData : [length(1 byte)][width(1 byte)][size(4 bytes]

But, usually, this may create following or undefined result.

pData : [length(1 byte)][width(1 byte)][padding(2 bytes)][size(4 bytes)]

So, we should not use like above(accessing memory directly). We can use 'struct' instead.
But, use 'memcpy' if above way is really needed.

(*) ==> memcpy(pt, &size, sizeof(size));

We should always keep it mind that data is aligned. So, directly accessing memory address to read or write data always has risk of compatibility with align.

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

Let's remind about endianness.

big-endian : most significant byte first.
little-endian : least significant byte first.

How about following code?

UINT16 b;
UINT8* p;
p = &b;
b = 0xABCD;
printf("%x, %x\n", p[0], p[1]);

This make different result according to endianness.

LE : CD, AB
BE : AB, CD

So, avoid kind of coding!

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

#define STORE_LE16(bUFF,nUM) ( ((bUFF)[1] = (UINT8) ((nUM)>>8)), \

                              ((bUFF)[0] = (UINT8) (nUM)) )

#define STORE_LE32(bUFF,nUM) ( ((bUFF)[3] = (UINT8) ((nUM)>>24)),    \
                              ((bUFF)[2] = (UINT8) ((nUM)>>16)),     \
                              ((bUFF)[1] = (UINT8) ((nUM)>>8)),      \
                              ((bUFF)[0] = (UINT8) (nUM)) )

/* Store value into a bUFFer in Big Endian format */
#define STORE_BE16(bUFF,nUM) ( ((bUFF)[0] = (UINT8) ((nUM)>>8)),     \
                              ((bUFF)[1] = (UINT8) (nUM)) )

#define STORE_BE32(bUFF,nUM) ( ((bUFF)[0] = (UINT8) ((nUM)>>24)),    \
                              ((bUFF)[1] = (UINT8) ((nUM)>>16)),     \
                              ((bUFF)[2] = (UINT8) ((nUM)>>8)),      \
                              ((bUFF)[3] = (UINT8) (nUM)) )

/* Little Endian to Host integer format conversion macros */
#define LEtoHost16(ptr)  (U16)( ((U16) *((U8*)(ptr)+1) << 8) | \
                                ((U16) *((U8*)(ptr))) )

#define LEtoHost32(ptr)  (U32)( ((U32) *((U8*)(ptr)+3) << 24) | \
                                ((U32) *((U8*)(ptr)+2) << 16) | \
                                ((U32) *((U8*)(ptr)+1) << 8)  | \
                                ((U32) *((U8*)(ptr))) )

/* Big Endian to Host integer format conversion macros */
#define BEtoHost16(ptr)  (U16)( ((U16) *((U8*)(ptr)) << 8) | \
                                ((U16) *((U8*)(ptr)+1)) )

#define BEtoHost32(ptr)  (U32)( ((U32) *((U8*)(ptr)) << 24)   | \
                                ((U32) *((U8*)(ptr)+1) << 16) | \
                                ((U32) *((U8*)(ptr)+2) << 8)  | \
                                ((U32) *((U8*)(ptr)+3)) )
[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

Conflicting symbol name with library is not rare.
So, I want suggest my personal opinion to avoid this.

1. Before release code/library, change all symbol name of source code into unique name (random string) with tool.
2. Determine appropriate symbol name that should be exported.
  (There can be two options. (*a)One is "changing exported symbols into agreed name". (*b)The other is "providing header file that includes all exported symbol with recommended name. And user can re-define necessary or conflicting symbol into expected one")

Let's see the example.

 a. (original source code)
  ...
  MY_UINT32 my_name;
  ...
  MY_UINT16 company_name;
  ..

 b. (symbol-changing-tool setting) - change symbol from 'a.'
  ...
  MY_UINT32 => FooRgYaIIkdjdtq40238dkkRkwUTTT00001
  MY_UINT16 => FooRgYaIIkdjdtq40238dkkRkwUTTT00002
  my_name => FooRgYaIIkdjdtq40238dkkRkwUTTT00003
  compay_name => FooRgYaIIkdjdtq40238dkkRkwUTTT00004
  ...

 c. (auto-modified original source code)
  ...
  FooRgYaIIkdjdtq40238dkkRkwUTTT00001 FooRgYaIIkdjdtq40238dkkRkwUTTT00003;
  ...
  FooRgYaIIkdjdtq40238dkkRkwUTTT00002 FooRgYaIIkdjdtq40238dkkRkwUTTT00004;
  ...

-------- (*a) -------------

 d1. agreed name
  MY_UINT32 => UINT32
  MY_UINT16 => UINT16
  my_name => company_name
  company_name => firm_name

 d2(*a). (symbol-changing-too setting) - change symbol from 'c.' based on 'd.'
  FooRgYaIIkdjdtq40238dkkRkwUTTT00001 => UINT32
  FooRgYaIIkdjdtq40238dkkRkwUTTT00002 => UINT16
  FooRgYaIIkdjdtq40238dkkRkwUTTT00003 => company_name
  FooRgYaIIkdjdtq40238dkkRkwUTTT00004 => firm_name

---------- (*b) ---------

 d. (header file that has recommended symbol)
  /*symbol_match.h */
  /*=============== symbol-matching table ================= */
  ...
  #define UINT32 FooRgYaIIkdjdtq40238dkkRkwUTTT00001
  #define UINT16 FooRgYaIIkdjdtq40238dkkRkwUTTT00002
  #define my_name FooRgYaIIkdjdtq40238dkkRkwUTTT00003
  #define company_name FooRgYaIIkdjdtq40238dkkRkwUTTT00004
  ...

--------------------

 e. (Releasable code - base source code for building library)
  ...
  UINT32 company_name;
  ...
  UINT16 firm_name;
  ...

I think this way is worth considering to make very portable library.

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

'virtual' is runtime-deterministic keyword. But 'inline' is compile-time-deterministic keyword....
I think 'virtual' has priority.... I haven't tested it yet!!! :-)
[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

At first, see
 virtual inheritance in wikipedia to know about virtual inheritance.

There are lots of articles about this. So, I am adding 'Real' example tested on "MSVC2005 Express".
- Don't use 'debug watch' of VC. Sometimes it show wrong information!.
(Note: C++ standard doens't define anything about the way of implementing dynamic polymorphism. So, results are dependent on compiler.)

==================================
Non-Virtual Inheritance
class Animal
{
  virtual void Eat(){};
  int animal;
};

Animal
  +-----------------+
  |   __vfptr       |---> Animal::Eat()
  +-----------------+
  |   int animal    |
  +-----------------+

class Mammal : public Animal
{
  virtual void Run(){};
  int mammal
};

Mammal
  +-----------------+
  |   __vfptr       |---> Animal::Eat()
  +-----------------+     Mammal::Run()
  |   int animal    |
  +-----------------+
  |   int mammal    |
  +-----------------+

class Winged : public Animal
{
  virtual void Flap(){};
  int winged
};

Winged
  +-----------------+
  |   __vfptr       |---> Animal::Eat()
  +-----------------+     Winged::Flap()
  |   int animal    |
  +-----------------+
  |   int winged    |
  +-----------------+

class Bat : public Mammal, public Winged
{
  virtual void Hang(){};
};

Bat
  +-----------------+
  |   __vfptr       |---> Animal::Eat() (*1) [from Mammal]
  +-----------------+     Mammal::Run()
  |   int animal    |     Bat::Hang()
  +-----------------+
  |   int mammal    |
  +-----------------+
  |   __vfptr       |---> Animal::Eat() (*2) [from Winged]
  +-----------------+     Winged::Flap()
  |   int animal    |
  +-----------------+
  |   int winged    |
  +-----------------+

(Address of (*1) and (*2) is different.)

======================================
Virtual Inheritance

class Animal
{
public:
  Animal():animal(){}
  virtual void Eat(){};
  int animal;
};

Animal
  +-----------------+
  |   __vfptr       |---> Animal::Eat()
  +-----------------+
  |   int animal    |
  +-----------------+

class Mammal : public virtual Animal
{
public:
  Mammal():mammal(){}
  virtual void Run(){};
  int mammal;
};

Mammal
  +-----------------+
  |   __vfptr       |---> Mammal::Run()
  +-----------------+
  |   ???????????   |
  +-----------------+
  |   int mammal    |
  +-----------------+
  |    __vfptr      |---> Animal::Eat()
  +-----------------+
  |   int animal    |
  +-----------------+

class Winged : public virtual Animal
{
public:
  Winged():winged(){}
  virtual void Flap(){};
  int winged;
};

Winged
  +-----------------+
  |   __vfptr       |---> Winged::Flap()
  +-----------------+
  |   ???????????   |
  +-----------------+
  |   int winged    |
  +-----------------+
  |    __vfptr      |---> Animal::Eat()
  +-----------------+
  |   int animal    |
  +-----------------+

class Bat : public Mammal, public Winged
{
  virtual void Hang(){};
};

Bat
  +-----------------+
  |   __vfptr       |---> Mammal::Run()
  +-----------------+     Bat::Hang()
  |   ??????????    |
  +-----------------+
  |   int mammal    |
  +-----------------+
  |   __vfptr       |---> Winged::Flap()
  +-----------------+
  |   ??????????    |
  +-----------------+
  |   int winged    |
  +-----------------+
  |    __vfptr      |---> Animal::Eat()
  +-----------------+
  |   int animal    |
  +-----------------+
===============================

NOTE: I have no idea what "?????" means. I think this is only for internal use of VC.

Here is view of this.

"---." : reference member (p.xxx)
"--->" : pointer member (p->xxx)

Non-virtual inheritance
  bat
  |----. Mammal
  | |----. Animal
  | | |----. __vfptr ( --> 0x00415770) --- (*1)
  | | | |----> Animal::eat(void)
  | | | |----> Mammal::setHairColor(void)
  |
  |----. WingedAnimal
  | |----. Animal
  | | |----. __vfptr ( --> 0x00415760) --- (*2)
  | | | |----> Animal::eat(void)
  | | | |----> WingedAnimal::flap(void)

Virtual inheritance case
  bat
  |----. Mammal
  | |----. Animal
  | | |----. __vfptr ( --> 0x00415788) --- (*3)
  | | | |----> Animal::eat(void)
  | |----. __vfptr
  | | |----> Mammal::setHairColor(void)
  |
  |----. WingedAnimal
  | |----. Animal
  | | |----. __vfptr ( --> 0x00415788) --- (*4)
  | | | |----> Animal::eat(void)
  | |----. __vfptr
  | | |----> WingedAnimal::flap(void)

We should focus on that pointed address indicated at (*1) and (*2) is different, but the one at (*3) and (*4) is same - actually, it's not separated entity, it's same one. That is, there is one vftable for Animal class.

Now we can know the way of virtual inheritance.

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

See following example codes.

class A
{
public:
    virtual int a(void) {return 1; }
    virtual int b(void) {return 11;}
    int         c(void) {return 21;}
};

class B
{
public:
    virtual int a(void) {return 2; }
    virtual int b(void) {return 12;}
    int         c(void) {return 22;}
};

class C : public A, public B
{
public:
    virtual int a(void) { return 3; }
};

void main(void)
{
    C c;
    A* pa = &c;
    B* pb = &c;
    printf("%d / %d / %d\n", pa->a(), pb->a(), c.a()); // OK ---(*1)
    printf("%d\n", c.b());  // Compile Error due to ambiguous access ---(*2)
    printf("%d\n", c.c());  // Compile Error due to ambiguous access ---(*3)
}

In case of (*2) and (*3), Compiler gives 'Error' due to ambiguity - A::b()/B::b(). It's clear.
But, there is no ambiguity in case (*1). Function 'a' is declared as 'virtual' in A and B. And 'a' also overridden in C. So, all three parameters of 'printf' means 'C::a()'.

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

'shift' operator in C extends sign bit.

int a = 0xffffffff;
a = a>>8; // a == 0xffffffff

Due to sign of 'a' is minus, '>>8' preserve it's sign.
But, 'unsigned' value is always '>=0' So, sign bit doesn't need to be extended. So, front parts is filled with '0'.

unsigned int a = 0xffffffff
a = a >>8; // a == 0x00ffffff
[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

This is tip to define 'enum' that has quite lots of items and important information - ex thread id, event id, etc...

(*1)

// File : "main"

enum
{
    enum01,
    enum02,
    ...
}
...

This is not recommended.
How about using following way?

(*2)

// File : "enum.h "

DEF_ENUM(enum01)
DEF_ENUM(enum02)
...

------------------

// File : "main

#define DEF_ENUM(x)   x,
enum
{
    #include "enum.h"
}
#undef DEF_ENUM

Why this way is better? Let's assume that you want to print 'enum' values.
In (*1) case, only number value can be printed. But in (*2) case, even enum name - string - can be easily printed by following way.

// File : "Enum_str.c"

#define DEF_ENUM(x)   #x,
static const char* enum_str[] =
{
    #include "enum.h"
};
...

printf("%s", enum_str[enum_id]);

It is good, isn't it?
Except for this, you can find other lots of useful ways by using macro.

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

====================================================

// From MSDN

#define paster( n ) printf( "token" #n " = %d", token##n )
int token9 = 9;

If a macro is called with a numeric argument like

paster( 9 );

the macro yields

printf( "token" "9" " = %d", token9 );

which becomes

printf( "token9 = %d", token9 );

====================================================

',' is used as parameter separator in C/C++. So, function which uses variable number of parameter - like "logger(const char* format, ...)" - is difficult to present by using macro. (Some compilers support variable number of parameter in macro too. But, most are not.)
In this case, we can make those be on parameter by groupping all parameters with "()".
For example,

#ifdef _DEBUG_
#   define LOGGER(X) logger X
#else // _DEBUG_
// we don't need to run log function in release build!
#   define LOGGER(X)
#endif // _DEBUG_
...
LOGGER((”print :%d, %d”, a, b)); // == logger(“print:%d, %d”, a, b);
...

=====================================================

To track a function, following way is very common.

// foo_fnc. h :
#ifdef CODE_DEBUG
#   define REAL_fnc(a, b) real_fnc(a, b, __FILE__, __LINE__)
#else
#   define REAL_fnc(a,b) real_fnc(a,b)
#endif

But, In following cases, some compiler raises error.

#ifdef 1
REAL_fnc(a,
#else
NEW_REAL_fnc(a,
#endif
    b);

Yes. It's a kind of porting issue.
In this case, we can use following walk-around.

// foo_fnc. h :
#ifdef CODE_DEBUG
    typedef int (* RealType_Fnc)(int, int)
#   define REAL_fnc real_fnc_wrap(__FILE__, __LINE__)
    extern RealType_Fnc real_fnc_wrap(char*, int);
#else
#   define REAL_fnc(a,b) real_fnc(a,b)
#endif

---------

// foo_fnc.c
...(omitted)
RealType_Fnc real_fnc_wrap(char* fileName, int line)
{
    printf(“%s : %d”, fileName, line);
    return real_fnc;
}

+ Recent posts