Daily Archives: February 24, 2014

migration C#, Java, C++ (day 1)

logo

This is day 1 of this series. I am covering some tricky basics between the two languages before we get more complicated. All should be self-explanatory. There is no clear structure yet. I just picked some examples that are worth mentioning.
There is a lot of code that cannot be written in C# or C++. Sometimes the differences are quite big. I am still trying to find a solution to show such properly in a comparison without just documenting each language by itself.

Arrays

// single-dimensional array
int[] a1 = new int[5];
Console.WriteLine(a1.Length); // 5

// rectangular array
int[,] a2 = new int[3, 4];
Console.WriteLine(a2.Length); // 12
Console.WriteLine(a2.GetUpperBound(0)); // 2
Console.WriteLine(a2.GetUpperBound(1)); // 3

// jagged arrays
int[][] a3 = new int[5][];
for (int i = 0, n = a3.Length; i < n; i++) a3[i] = new int[i + 3];
Console.WriteLine(a3.Length); // 5
Console.WriteLine(a3[3].Length); // 6
Console.WriteLine(a3.GetUpperBound(0)); // 4
// single-dimensional array
int[] a1 = new int[5];
System.out.println(a1.length); // 5

// rectangular array
int[][] a2 = new int[3][4];
System.out.println(a2.length); // 3
System.out.println(a2[0].length); // 4

// jagged arrays
int[][] a3 = new int[5][];
for (int i = 0, n = a3.length; i < n; i++) a3[i] = new int[i + 3];
System.out.println(a3.length); // 5
System.out.println(a3[3].length); // 6
// single-dimensional array
int* a0 = new int[5]; // Size cannot be determined. Use std::vector.

int a1[5];
cout << sizeof(a1) << endl;    // 20 bytes
cout << sizeof(a1)/sizeof(a1[0]) << endl;    // 5 elements

// rectangular array
unsigned int a2[3][4];
cout << "int[3][4]: " << sizeof(a2) << endl;    // 48
cout << "   int[4]: " << sizeof(*a2) << endl;   // 16
cout << "      int: " << sizeof(**a2) << endl;  // 4
cout << "       a2: " << a2 << endl;            // 0x28fed0
cout << "(*a2) + 1: " << (*a2) + 1 << endl;     // 0x28fed4 (4 higher)
cout << "   a2 + 1: " << a2 + 1 << endl;        // 0x28fee0 (16 higher)

// jagged arrays
int** a3 = new int*[5];
for(size_t i = 0; i < 5; ++i) a3[i] = new int[i + 3];
for(size_t i = 0; i < 5; ++i) delete[] a3[i];
delete[] a3;

Pointers

// call by reference vs. call by value
void CallByValue(int x) { x = 6; }
void CallByRefernce1(ref int x) { x = 1; }
void CallByRefernce2(out int x) { x = 2; }
public int func(int x) { return x; }

int h = 3;
CallByValue(h); Console.WriteLine(h); // 3
CallByRefernce2(out h); Console.WriteLine(h); // 2
CallByRefernce1(ref h); Console.WriteLine(h); // 1

// this is a simple delegate (not a pointer)
Func<int, int> f = func;
Console.WriteLine(f(5)); // 5
public final class delegateWrapper<T> {
  public T invoke(T t) {
    return t;
  }
} // class

public final class boxingWrapper<T> {
  public T value;

  public boxingWrapper(T xValue) {
    value = xValue;
  }
} // class

private void CallByValue(int x) { x = 6; }
private void CallByRefernce(boxingWrapper<Integer> x) { x.value = 1; }


int h = 3;
boxingWrapper<Integer> lWrapper = new boxingWrapper<Integer>(h);

CallByValue(h); // 3
System.out.println(h);
CallByRefernce(lWrapper);
h = lWrapper.value; // 1
System.out.println(h);

// there are no pointers or delegates in Java
delegateWrapper<Integer> lDelegate = new delegateWrapper<Integer>();
h = lDelegate.invoke(5);
System.out.println(h); // 5
// call by reference vs. call by value
void CallByValue(int x) { x = 6; }
void CallByRefernce(int &x) { x = 1; }
int func(int x) { return x; }

int h = 3;
CallByValue(h);    cout<<h<<endl; // 3
CallByRefernce(h); cout<<h<<endl; // 1

// pointer to a method
int (*f)(int) = 0;
f = &func;
cout<< f(5) << " " << (*f)(5) << endl; // 5 5

// pointer to integers (not available in C#)
int *p1;    // pointer to an integer
int p2[3];  // an array of 3 integers
int *p3[3]; // an array of 3 pointers to integers
int (*p4)[3]; // a pointer to an array of 3 integers
int *(&p5)[3] = p3; // a reference to an array of 3 pointers to integers
int *(*p6[3])[4]; // an array of 3 pointers to an array of 4 pointers to integers
int **(*p7[2])[3]; // an array of 2 pointers to an array of 3 pointers to pointers to integers

Strings

string s = "Hello World!"; // Unicode (24 bytes)
Console.WriteLine(s.Length); // 12
if (s.CompareTo("abc") > 0) Console.WriteLine("larger");

for (int i = 0, n = s.Length; i < n; i++) Console.Write(s[i] + " ");
Console.WriteLine();
foreach (char lChar in s) Console.Write(lChar + " ");
Console.WriteLine();

int lPosition = s.IndexOf("ll", 0);
s = s.Remove(lPosition, 2) + " / " + s.Substring(lPosition, 2);
Console.WriteLine(s);
String s = "Hello World!"; // Unicode (24 bytes)
System.out.println(s.length()); // 12
if (s.compareTo("abc") > 0) System.out.println("larger");

for (int i = 0, n = s.length(); i < n; i++) System.out.print(s.charAt(i) + " ");
System.out.println();
char[] lChars = s.toCharArray();
for (char lChar : lChars) System.out.print(lChar + " ");
System.out.println();

int lPosition = s.indexOf("ll", 0);
// there is no remove, so we need to simulate it
String h = s.substring(0, lPosition) + s.substring(lPosition + 2);
s = h + " / " + s.substring(lPosition, lPosition + 2);
System.out.println(s);
// strings (null terminated ASCII codes)
string s = "Hello World!";  // == {’H’, ’e’, ’l’, ’l’, ’o’, ’ ’, ’W’, ’o’, ’l’, ’d’, ’!’, ’\0’}
cout<< s << ", length: " << s.length() << endl;
cout<< sizeof(s) << endl; // pointer size
if (s < "abc") cout << "abc is larger" << endl; // operator overloaded in string.h

for (int i = 0;s[i] != '\0'; i++) cout << s[i] << " ";
cout << endl;
for (int i = 0, n = s.length(); i < n; i++) cout << s.at(i) << " "; // includes boundary checks and exception handling
cout << endl;
for (char &c : s) cout << c << " "; // includes boundary checks and exception handling
cout << endl;
int lPosition = s.find("ll", 0);
s = s.erase(lPosition, 2) + " / " + s.substr(lPosition, 2);
cout << s << endl;

// wstring holds unicode characters
// (wchar_t is 2 bytes on Windows, 4 bytes on Linux)
const wstring lWString = L"Hello wide world :)";
wcout<<lWString<<endl;  // direct output

string lString(lWString.begin(), lWString.end());
cout<<lString<<endl;

#define

// preprocessor #define is used to set flags
#if DEBUG
   Console.WriteLine("DEBUG CODE");
   try {
      throw new Exception();
   }
   catch (Exception ex) {
      Console.WriteLine(ex.StackTrace);
   }
#else
   Console.WriteLine("PROD CODE");
#endif
public static boolean DEBUG = true;

// There are no preprocessors in Java.
// To get as close as possible to the idea of preprocessors you
// can use public static variables or Dependency Injection.
public void test() {
  if (DEBUG) {
      System.out.println("DEBUG CODE");
      try {
        throw new RuntimeException();
      }
      catch (RuntimeException ex) {
        for (StackTraceElement x : ex.getStackTrace()) System.out.println(x.toString());
      }
  } else System.out.println("PROD CODE");
}
// preprocessor #define
#define OMG "Oh my god!\n"
cout << OMG << endl;

#define add(a, b, c) a + b + c + 1
cout << add(1, 2, 3) << endl; // 7

#define DEBUG
#ifdef DEBUG
    cout << "DEBUG CODE" << endl;
#else
    count << "PROD CODE" << endl;
#endif

cout << endl;
cout << "This is the line " << __LINE__ << " of file " << __FILE__ << endl;
cout << "Compilation date " << __DATE__ << " " << __TIME__ << endl;

struct vs. class

struct MyStruct { public double x; }  // value type
class MyClass { public double x; }    // reference type

MyStruct lStruct1 = new MyStruct();
MyStruct lStruct2 = lStruct1; // creates a copy of lStruct1
lStruct2.x = 1.0;
lStruct1.x = 99.9;
Console.WriteLine(lStruct2.x); // 1.0 !

MyClass lClass1 = new MyClass();
MyClass lClass2 = lClass1;  // only assigns the reference
lClass2.x = 1.0;
lClass1.x = 99.9;
Console.WriteLine(lClass2.x); // 99.9 !
// there are no user-defined value types like struct in Java
public class MyClass { public double x; }

private MyClass lClass1 = new MyClass();
private MyClass lClass2 = lClass1; // assigns the reference
lClass2.x = 1.0;
lClass1.x = 99.9;
System.out.println(lClass2.x); // 99.9
// Structs in C++ are like classes.
// The main difference is that the default for structs is public, whereas the default for classes is private.
// Some people say that structs are for data (no methods) only. This is not true. Both can have methods. 

Cast Operations

public class Dog { }
public class Husky : Dog { }
public class StyleGuide { }

// cast operations
double pi = 3.14159265;
int lInt = (int)pi;
double d = lInt;
Console.WriteLine(d); // 3.0

Dog lDog = new Husky();
Husky lHusky = lDog as Husky;
if (lHusky != null) Console.WriteLine("A husky is a dog");
StyleGuide lStyle = new StyleGuide();
//lHusky = (Husky)lStyle; //   won't compile
public class Dog { }
public class Husky extends Dog { }
public class StyleGuide { }

double pi = 3.14159265;
int lInt = (int)pi;
double d = lInt;
System.out.println(d); // 3.0

Dog lDog = new Husky();
Husky lHusky = (Husky)lDog;
if (lHusky != null) System.out.println("A husky is a dog");
StyleGuide lStyle = new StyleGuide();
// lHusky = (Husky)lStyle; //   won't compile
// cast operations
double pi = 3.14159265;
int    lInt = static_cast<int>(pi);
double d = lInt;
cout<<d<<endl; // 3.0

Dog *lDog = new Husky();
Husky *lHusky = dynamic_cast<Husky*>(lDog);
if (lHusky != 0) cout<<"A husky is a dog"<< endl;
StyleGuide *lStyle;
lHusky = dynamic_cast<Husky*>(lStyle);
if (lHusky == 0) cout<<"A StyleGuide is not a dog"<< endl;

const char* lConst = "Hello World";
char* lVariable = const_cast<char*>(lConst);

long lAddress = 5165786;
lDog = reinterpret_cast<Dog*>(lAddress);
if (lDog != 0) cout<<"What a funny dog"<< endl;

Collections:List

List<string> lList = new List<string>();
lList.Add("hello");
lList.Add("world");
foreach (var lItem in lList) Console.WriteLine(lItem);
lList.Clear();
lList = null;
java.util.ArrayList<String> lList = new java.util.ArrayList<String>();
lList.add("hello");
lList.add("world");
for (String lItem : lList) System.out.println(lItem);
lList.clear();
lList = null;
vector<wstring> lList = vector<wstring>();
lList.push_back(L"hello");
lList.push_back(L"world");
for (wstring &lItem : lList) wcout << lItem << endl;
lList.clear();

Our first class

using System;

namespace DemoApp.ToCpp {
   public class StyleGuide : IDisposable {

      private bool _Disposed = false;

      public StyleGuide() { }
      private double PrivateFunc(string s) { return 5.3; }
      public int PublicFunc(string s) { return 0; }
      protected string ProtectedFunc(string s) { return s; }

      ~StyleGuide() { Dispose(false); } // deconstructors call Finalize() of the base class

      public void Dispose() {
         Dispose(true);
         GC.SuppressFinalize(this);
      }

      protected virtual void Dispose(bool xDisposing) {
         if (_Disposed) return;
         if (xDisposing) {
            // free objects
         }
         _Disposed = true;
      } //

   } // class
} // namespace
package DemoApp.ToCpp;

public class StyleGuide {
  public StyleGuide() {}
  private double PrivateFunc(String s) { return 5.3; }
  public final int PublicFunc(String s) { return 0; }
  protected final String ProtectedFunc(String s) { return s; }

  @Override
  protected void finalize() throws Throwable {
    //
    // FreeResourcesHere();
    //
    super.finalize();
  } // destructor

} // class
#ifndef STYLEGUIDE_H
#define STYLEGUIDE_H

#include <iostream>
#include <string>

using namespace std;

class StyleGuide
{
    public:
        StyleGuide();
        virtual ~StyleGuide();
        int PublicFunc(string* s);
    protected:
        string ProtectedFunc(string* s);
    private:
        double PrivateFunc(string* s);
};

#endif // STYLEGUIDE_H
#include "StyleGuide.h"

StyleGuide::StyleGuide() {}

StyleGuide::~StyleGuide() {}

double StyleGuide::PrivateFunc(string *s) {
    return 5.3;
}

int StyleGuide::PublicFunc(string *s) {
    return 0;
}

string StyleGuide::ProtectedFunc(string *s) {
    return *s;
}