For starters this statement
int inputLength = sizeof(input)/ sizeof(char);
is redundant. As the array contains a string when within the for loop you can just check whether a current character is the terminating zero character '\0'.
Also pay attention to that in general a character array can be much larger than the string stored in the array. So using this variable calculated such a way in general can be wrong. It would be more correctly to use standard C function strlen if the length of a stored string is required.
.
Using this casting
int value = (int) input[i];
is actually is equivalent to
int value = input[i];
due to the integer promotion.
The type char can behave either as the signed type signed char or as the unsigned type unsigned char. To make the code independent on the behavior of the type char you need to cast each character to the type unsigned char.
So this assert
assert(value > -1);
does not useful.
An array with 256 elements of the type int is not very large. So you could define it with automatic storage duration. Also it will be logically consistent to use the type unsigned int instead of the signed type int in the array declaration.
Your code snippet can look like
char input[] = "Hello World";
unsigned int frequencies[256] = { 0 };
for ( const char *p = input; *p != '\0'; ++p )
{
++frequencies[( unsigned char )*p];
}
PrintFrequencies(frequencies);