//
//  Constants to detect errors
//

#include <iostream>

int my_strlen(char *s)
{
    char *p = s;
    // here the programmer has made fatal error
    while ( ! (*p = 0) ) ++p;
    return p - s;
}

// This program likely cause run-time error
int main()
{
    char t[] = "Hello";
    std::cout << my_strlen(t) << std::endl;
    return 0;
}


// version 2:


#include <iostream>

// this is the correct declaration of parameter
int my_strlen(const char *s)
{
    // ... which requires const char* here:
    const char *p = s;

    // 7_const.cpp: In function `int my_strlen(const char*)':
    // 7_const.cpp:8: assignment of read-only location
    while ( ! (*p = 0) ) ++p;
    return p - s;
}

int main()
{
    char t[] = "Hello";
    std::cout << my_strlen(t) << std::endl;
    return 0;
}


// version 3: correct 


#include <iostream>

// this is the correct declaration of parameter
int my_strlen(const char *s)
{
    // ... which requires const char* here:
    const char *p = s;

    // 7_const.cpp: In function `int my_strlen(const char*)':
    // 7_const.cpp:8: assignment of read-only location
    while ( ! (*p == 0) ) ++p;
    return p - s;
}

int main()
{
    char t[] = "Hello";
    std::cout << my_strlen(t) << std::endl;  // t converted to const char *
    return 0;
}


//
//  Defensive programming style
//

#include <iostream>

int my_strlen(char *s)
{
    char *p = s;
    // write immutable on the left side
    while ( ! (0 == *p) ) ++p;
    return p - s;
}





//
// Const cast
//
#include <iostream>

void f()
{
  const int ci = 10;
  int *ip = const_cast<int *>(&ci);
  ++*ip;
  std::cout << ci << " " << *ip << std::endl;
}

int main()
{
  f();
  return 0;
}


$ g++ -ansi -pedantic -Wall a.cpp
$ ./a.out
10 11





#include <iostream>

void f(const int ci)
{
  int *ip = const_cast<int *>(&ci);
  ++*ip;
  std::cout << ci << " " << *ip << std::endl;
}

int main()
{
  const int i = 10;
  f(i);
  return 0;
}


$ g++ -ansi -pedantic -Wall a.cpp  # same with -O3
$ ./a.out
11 11




~