//
//  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++ non-volatile.cpp
$ ./a.out
10 11





#include <iostream>

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

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


$ g++ volatile.cpp
$ ./a.out
11 11







	.file	"non-volatile.cpp"
        :
        :
_Z1fv:
.LFB1020:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	pushq	%rbx
	subq	$24, %rsp
	.cfi_offset 3, -24
	movl	$10, -28(%rbp)
	leaq	-28(%rbp), %rax
	movq	%rax, -24(%rbp)
	movq	-24(%rbp), %rax
	movl	(%rax), %eax
	leal	1(%rax), %edx
	movq	-24(%rbp), %rax
	movl	%edx, (%rax)
	movq	-24(%rbp), %rax
	movl	(%rax), %ebx
	movl	$10, %esi
	movl	$_ZSt4cout, %edi
	call	_ZNSolsEi
	movl	$.LC0, %esi
	movq	%rax, %rdi
	call	_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
	movl	%ebx, %esi
	movq	%rax, %rdi
	call	_ZNSolsEi
	movl	$_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, %esi
	movq	%rax, %rdi
	call	_ZNSolsEPFRSoS_E
	addq	$24, %rsp
	popq	%rbx
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc



	.file	"volatile.cpp"
        :
        :
_Z1fv:
.LFB1020:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	pushq	%rbx
	subq	$24, %rsp
	.cfi_offset 3, -24
	movl	$10, -28(%rbp)
	leaq	-28(%rbp), %rax
	movq	%rax, -24(%rbp)
	movq	-24(%rbp), %rax
	movl	(%rax), %eax
	leal	1(%rax), %edx
	movq	-24(%rbp), %rax
	movl	%edx, (%rax)
	movq	-24(%rbp), %rax
	movl	(%rax), %ebx
	movl	-28(%rbp), %eax
	movl	%eax, %esi
	movl	$_ZSt4cout, %edi
	call	_ZNSolsEi
	movl	$.LC0, %esi
	movq	%rax, %rdi
	call	_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
	movl	%ebx, %esi
	movq	%rax, %rdi
	call	_ZNSolsEi
	movl	$_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, %esi
	movq	%rax, %rdi
	call	_ZNSolsEPFRSoS_E
	addq	$24, %rsp
	popq	%rbx
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc



$ diff non-volatile.s volatile.s
1c1
< 	.file	"non-volatile.cpp"
---
> 	.file	"volatile.cpp"
31c31,32
< 	movl	$10, %esi
---
> 	movl	-28(%rbp), %eax
> 	movl	%eax, %esi