Open addressed hash table
Regarding the problem of the error case where either the table or key is null in hash_code, you might pass in ht->size instead of ht, thus halving the problem.  If you redefine the 'contract' so that a NULL key is treated the same as an empty string "", then you no longer have an error case.

Some comments on the code:


I'd expect a short description of the nature of the hashtable and how it is used at the start.
INITIAL_VALUE and M should be const
function parameters should be const where possible
return values not stated in headers
I would omit things like 'Function which'... from comments.  If it is a function then this can be assumed.
hash_code uses -1 as an error code while set/rm_val use 0.  Inconsistent.
Generally, unsigned should be used for values that are not numeric, such as bitmaps, not for numbers that you don't intend to go negative (although size_t contradicts that).


create_table()


don't cast malloc return value
check malloc return
ht->buckets not initialised to 0; use calloc instead?
you could avoid the first malloc by passing in a pointer to a statically allocated HashTable or by defining the buckets array as a flexible member and then allocate the necessary total size

typedef struct HashTable {

 size_t size;
 char *buckets[];


} HashTable;


hash_code():


parameter ht: I'd pass in the size (ht->size) instead of ht.  In general, it is easier to test a function that takes simple scalar inputs than one that receives structures. 
use of strlen in loop control is inefficient; key size does not change but will be evaluated each loop.  Perhaps for (; *key; ++key) {...}
prefer spaces after ';' in for-loop conditions
return hash % ht-&gt;size; loses precision (compiler warning due to type conversion).  Just use int throughout unless your hash is ever going to be big enough for the extra bit to matter.  If you thought it might get big enough (eg if using a processor where int is small) then you would have to check for overflow of an unsigned int too (I'm not suggesting you do that here).


get_val()


ignores -ve return from hash_code on error
last 4 lines reduce to return ht-&gt;buckets[hash];


set_val()


Better to return int, not unsigned int
hash is signed. Other uses are unsigned.
should val be duplicated (allocated)?  If not you have to tell the  caller that the string must be persistent (ie. the caller must not free it or pass a stack value).
else { return 0; } at the end of function can be reduced to return 0;
comment could be said to be excessive - describing what is obvious from the code; its first ',' should be '.'  I would say just: "Set hashtable value unless already set.  Returns 1 on success, 0 on failure (value already set)."


rm_val()


Better to return int, not unsigned int
ignores -ve return from hash_code on error
else { return 0; } at the end of function can be reduced to return 0;


main()


use EXIT_SUCCESS and EXIT_FAILURE