Showing posts with label C. Show all posts
Showing posts with label C. Show all posts

Thursday, May 6, 2010

Translating brainfuck code to ANSI-C code with BrainfuckToC

This is my latest project. An application that translates brainfuck code to ANSI-C code.

To download the sources, visit the Google Code brainfucktoc page.

I would also like to thank Reuben Sammut who is a contributer to the project.

Usage

bftoc <source file>

Example:

bftoc bfcode.b

This will take a brainfuck source file and output its equivalent C code.

If you want to redirect the output to a text file, run bftoc as follows:

bftoc bfcode.b > bfcode.c

Examples

Hello World
Input:
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
Output:
#include <stdio.h>
#include <stdlib.h>

int main () {
    char *ptr = calloc(10000, sizeof *ptr), *start = ptr;
    int i = 0;

    *ptr += 10;
    while (*ptr) {
        ++ptr;
        *ptr += 7;
        ++ptr;
        *ptr += 10;
        ++ptr;
        *ptr += 3;
        ++ptr;
        ++*ptr;
        ptr -= 4;
        --*ptr;
    }

    ++ptr;
    *ptr += 2;
    putchar(*ptr);
    ++ptr;
    ++*ptr;
    putchar(*ptr);
    *ptr += 7;
    putchar(*ptr);
    putchar(*ptr);
    *ptr += 3;
    putchar(*ptr);
    ++ptr;
    *ptr += 2;
    putchar(*ptr);
    ptr -= 2;
    *ptr += 15;
    putchar(*ptr);
    ++ptr;
    putchar(*ptr);
    *ptr += 3;
    putchar(*ptr);
    *ptr -= 6;
    putchar(*ptr);
    *ptr -= 8;
    putchar(*ptr);
    ++ptr;
    ++*ptr;
    putchar(*ptr);
    ++ptr;
    putchar(*ptr);

    free(start);
    return 0;
}

Saturday, February 27, 2010

Why can you write arr[n] == n[arr] in C ?

Try the following program in C :

#include <stdio.h>

int main () {
  int arr[] = {42};
  printf("%d", arr[0] == 0[arr]);
  return 0;
}

The above program prints out 1...ie, true.

But why...?

Well the reason the above works is because of how arrays are represented in C. In C, when referencing an array, you're just referencing a pointer to the first element :

int arr[] = {42, 39};
int x = arr[0];
int y = *(arr + 0);
// x == y

In the *(arr + 0) example, we are accessing the first element of the array by dereferencing the pointer to the first element arr plus the 0 offset.

int arr[] = {42, 39};
int x = arr[1];
int y = *(arr + 1);
// x == y

In the above example, we are accessing the second element with index 1.

Therefore, if *(arr + 1) evaluates to arr[1], then surely *(1 + arr) evaluates to 1[arr] according to elementary math...because addition is commutative, which means that the order of the operands does not matter, as it produces the same result.

The reason for this is because since C was designed back in the 70s, computers did not have much memory and thus the C compiler didn't do much syntax checking. Therefore, something like arr[i] was blindly translated to *(arr + i)

Tuesday, November 17, 2009

Passing a pointer by reference in C

Today I needed a way to pass a pointer to an int to a function, modify the location of that pointer (via malloc) in that function, and then access the modified pointer from outside the function (from the caller).

I tried to code it like such (incorrectly):

int f(int *arr, int n) {
    int i;
    arr = malloc( n * sizeof (*arr));
    for (i = 0; i < n; ++i, ++arr) {
        *arr = i;
    }
    arr -= i;
    printf("Second element (from function) : %d\n", *(arr + 1));
    return 0;
}

int main()
{
    int *arr;
    f(arr, 5);
    printf("Second element (from caller) : %d", *(arr + 1));
    free(arr);
    return 0;
}
This is the output:

Second element (from function) : 1
Second element (from caller) : 1032044593

As you can see from the above output, the correct element is displayed when accessing the array from the function, but when I try to access the array from outside of the function (after it has been malloced and data was added), the value displayed seemed like a value from an unmalloced address!

What was I doing wrong?

The problem with the above code is that I am passing the pointer to an int by value to the function; ie a copy of the pointer.  That is why when I changed its address, the change was only visible from inside the function.

The Correct Way

The correct way to do it is to pass a pointer to the pointer to int (int **arr) to the function, like such:

int f(int **arr, int n) { //arr is now a pointer to a pointer to int
    int i;
    int *temp = malloc(n * sizeof **arr); //declare and malloc temporary space
    for (i = 0; i < n; ++i, ++temp) {
        *temp = i;
    }
    temp -= i;

    *arr = temp;  //Assign the value of the inputted location to the temporary one created earlier on

    printf("Second element (from function) : %d\n", *(temp + 1));
    return 0;
}

int main()
{
    int *arr;
    f(&arr, 5);  //The address of the pointer is now passed, not the pointer itself
    printf("Second element (from caller) : %d", *(arr + 1));
    free(arr);
    return;
}
Now the output from the above function is correct:

Second element (from function) : 1
Second element (from caller) : 1


Monday, November 16, 2009

Number of elements in an array in C

Take the following piece of code:
int main()
{
    int nums[] = {1,2,3,4,5};
    printf("Outside: %d\n",sizeof(nums) / sizeof(*nums));
    f(nums);
    return 0;
}

int f(int nums[]) {
    printf("Inside: %d\n",sizeof(nums) / sizeof(*nums));
}

Here is the output of the above code:
Outside: 5
Inside: 1
As you can see from the above output, when the calculation is done in the scope where the array was initialized, the correct output is displayed; but when it is passed to a function, the calculation fails!
This is because the formal argument int nums[]  does not contain any information about the array whereas the declaration of the array in the main function contains an implicit size  (determined by the number of items in the value), so as long as you use the variable in the main function (ie where it was declared), the compiler knows the size of the array.

When you send the array as a parameter to the f function, there is no information about the size sent along, it's just a pointer to an array of unknown size. The f function could be called from anywhere, so the compiler can't use the information about the variable in the main function.
If you want to know the size of the array in the f function, you have to send that along with the array as another parameter.


Saturday, November 14, 2009

Greatest Common Divisor and Least Common Multiple functions in C

Below are two functions (with a sample application) that calculate the Greatest Common Divisor and Least Common Multiple of two numbers; a,b

#include <stdio.h>

int gcd(int x, int y);
int lcm(int x, int y);

int main()
{
    int x = 156;
    int y = 156;

    int g = gcd(x,y);
    int l = lcm(x,y);

    printf("GCD (%d, %d) : %d\n", x,y,g);
    printf("LCM (%d, %d) : %d\n", x,y,l);
}

int gcd(int x, int y) {
    /*;
        a = qb + r,  0 <= r < b

        a => dividend, q => quotient, b => divisor, r => remainder
    */
    if (x == y) {
        return x /*or y*/;
    }

    int dividend = x, divisor = y, remainder = 0, quotient = 0;

    do {
        remainder = dividend % divisor;
        quotient = dividend / divisor;

        if(remainder) {
            dividend = divisor;
            divisor = remainder;
        }
    }
    while(remainder);

    return divisor;
}

int lcm(int x, int y) {
    /*
        lcm(x,y) = (x * y) / gcd(x,y)
    */
    return x == y ? x /*or y*/ : (x * y) / gcd(x,y);
}

Wednesday, October 21, 2009

Passing multi-dimensional arrays to functions in C

Here is how to initialize and pass multi-dimensional arrays to functions in ANSI C :

void printArray(int **array, int m, int n)
{
    int i, j;
    for(i = 0; i < m; i++) {
        for(j = 0; j < n; j++) {
            printf("%d\n", array[i][j]);
        }
    }
}

int main()
{
      int i, j, k = 0, m = 5, n = 20;
      int **a = malloc(m * sizeof(*a));
   
      //Initialize the arrays
      for (i = 0; i < m; i++) { 
          a[i]=malloc(n * sizeof(*(a[i])));
      }
      for (i = 0; i < m; i++) {
          for (j = 0; j<n; j++) {
              k++; 
              a[i][j] = k;
          }
      }
   
      printArray(a, m, n);
      
      //Free allocated memory of the array
      for (i = 0; i < m; ++i) {
        free(a[i]);
      }
      free(a);
   
      return 0;
}