essay on programming languages, computer science, information techonlogies and all.

Sunday, March 10, 2019

C++ Pointer

Here you can refresh your memory about pointer.

Pointer and Reference

Pretty basic, Right ?

int a = 1234;
int *pa = &a;    // pa is pointer of a
*pa = 1111;      // assignment on *pa will change a also

int &ra = a;     // ra is reference of a
ra = 4321;       // assignment on ra will change a also

Function return value using reference or pointer

Which do you prefer ? * or & ?

int AddAndMultiply(int a, int b, int& mult)
{
  mult = a * b;
  return a + b;   
}

int AddAndMultiplyV3(int a, int b, int* mult)
{
  *mult = a * b;
  return a + b;
}

int mult = 0;
int sum = AddAndMultiply(1, 2, mult);
sum = AddAndMultiplyV3(1, 2, &mult);

Function return struct

I can read this easily. But isn't struct make code slow by copying memory ? Are you sure ?

struct AddMult
{
  int Add;
  int Mult;
};

AddMult AddAndMultiplyV3(int a, int b)
{
  AddMult r;
  r.Add = a + b;
  r.Mult = a * b;
  return r;
}

AddMult r = AddAndMultiplyV3(1, 2);
sum = r.Add;
mult = r.Mult;

const at before or after


const int* cpa = &a;
*cpa = 42;           // compile error : cpa is pointing a constant variable, so you can't change the value
cpa = &b;            // but you can make it points other variable

const int& cra = a;
cra = 42;            // compile error : cra is referencing a constant variable, so you can't change the value

int* const pca = &a; 
*pca = 42;           // no problem : pca is constantly pointing a variable, and you can change the value of variable.
*pca = &b;           // compile error : but pca can't pointing to other variable.

mutable can be changed on const method

Then what's the point of const if there is mutable ?

struct AddData
{
  int A, B;
  mutable int C = 0;  // ok to be changed on const method.

  int AddAll() const  // This isn't supposed to change member variable. 
  {
    if (C == 0) { C = A + B; }
    return C;
  }
};

Endianess

big-endian puts significant bytes at lower address, while little-endian puts significant bytes at higher address.

uint32_t *pa = new uint32_t[4];
pa[0] = 0x12345678;     // note the little-endian
pa[1] = 0x87654321;
pa[2] = 0x10101010;
pa[3] = 0xCAFEBEEF;

*pa = 0xFFFFFFFF;
*(pa + 1) = 0xEEEEEEEE;

delete[] pa;

64 bit ponter

Each pointer is 64bits.

Packing at struct

Do you know how variable is packed in a struct ?

struct Foo
{
  uint32_t a;     // 4 Bytes
  char b;         // 2 Bytes
  uint16_t c;     // 2 Bytes
  bool d;         // 4 Bytes
  const char * e; // 4 Bytes
};

Foo foo;
Foo* pfoo = &foo;
foo = { 0x12345678, 'a', 0xCAFE, true, nullptr };

Function pointer

This syntax of putting type name in between retrun type and argument type and *, (, ). Can you remember it ?

int TestBar(char a) {  return a + 42;  }
int TestToo(char a) {  return a + 22;  }

typedef int(*FooFn)(char);  // Here you go!

FooFn f = TestBar;
int ret = f('a');
f = TestToo;
ret = f('b');

STL function pointer

Or how about STL style ?

int TestBar(char a) {  return a + 42;  }
int TestToo(char a) {  return a + 22;  }

using FooFn = std::function< int(char) >;  // Here you go again !

FooFn fn = TestBar;
int ret = fn('a');
fn = TestToo;
ret = fn('b');