Question: I have a C string and I'd like to shorten it, so that it gets cut from the first occurrence of '$'. Here's my code:

```
int char_search(char exp[], int s, char what) {
    int i, occurrence=-1;
    for (i=0; i < s && occurrence == -1; ++i)
        if (exp[i] == what)
            occurrence = i;

    return occurrence;
}

int shorten(char *exp, int maxlength, char *exp_new) {
    int l, i;
    l = char_search(exp, maxlength, '$');
    exp_new = (char *) malloc((l+1)*sizeof(char));
    exp_new[l] = '\0';
    for (i = 0; i<l; i++) 
        exp_new[i] = exp[i];

    return l;
}

```

The problem is it starts to overwrite the exp\_new pointer address, and only copies the first char to the actual array. Also, exp\_new returns NULL for some reason. (The string lengths might not be correct, but that shouldn't screw up the whole thing.)

Answer: 
When you want to return a pointer through a function parameter you need to use a double indirection:

```
int shorten(char *exp, int maxlength, char **exp_new)

```

A better signature would be

```
char* shorten(char *exp, int maxlength, int *length)

```

where you return the result directly.

*Edit*: When the function name "shorten" describes what it is ment to do the obvious result should be the shortened string. The length of that string resulting from the search function is a negligible result. The function could be changed so that the length parameter could accept a NULL pointer. In that case you could omitting a length result if it's not interesting for the caller. But that depends on the environment.
Several issues here:

1. To return a value from a function   

	* pass an address to an instance of what shall be returned and in the function dereference the address to store the data.
	* return the value from the function via `return`.
2. When addressing array elements no negative values are needed and a simple `int` might not be wide enough, so use `size_t`. If as in your case `-1` should also be used use `ssize_t`. Both such types are guaranteed by the C/POSIX Standard to be wide enough to address all of the machines memory and with this every possible array element.
3. In C don't cast the result of `malloc()/calloc()/realloc()`.
4. Declare `const` what is constant. This helps the compiler to optimise and you to write better code.
5. Always test functions which could fail whether they did. This applies to system calls as well as to your own functions.

Error checking is missing for:

	* `malloc()`
	* `char_search()`

---

Taking into account the points above your code might be changed to look like the following:

```
 ssize_t char_search(const char * exp, const size_t s, const char what) 
 {
   ssize_t occurrence = -1;

   for (size_t i = 0; i < s && occurrence == -1; ++i)
   {
     if (exp[i] == what)
     {
       occurrence = i;
     }
   }

   return occurrence;
}

ssize_t shorten(const char * exp, const size_t maxlength, char ** pexp_new) 
{
  ssize_t l = char_search(exp, maxlength, '$');
  if ((NULL != pexp_new) && (-1 != l)) /* This way if passing in NULL 
                                      as 3rd argument you just get l. */
  {
    *pexp_new = malloc((l + 1) * sizeof **pexp_new);
    if (NULL = *pexp_new)
    {
      l = -1; /* Indicate failure. */
    }
    else
    {
      size_t i = 0;

      (*pexp_new)[l] = '\0';

      for (; i < l; ++i) 
      {
        (*pexp_new)[i] = exp[i];
      }
    }
  }

  return l;
}

```