I have a set of structs that are uniquely identified by a uint16_t. There will never be more than 256 of these structs (due to reasons I won't get into a uint16_t must be used to identify the structs).
I would like to store these structs via an array of pointers. Since there will never be more than 256 structs, I would like to statically allocate an array of struct pointers with size 256. To do this though, I need a function to uniquely map uint16_t onto uint8_t.
Given that I will know all of the keys at runtime (though I won't know before runtime) is there an algorithm that exists that will give me a unique mapping (i.e. perfect hash) in general?
One caveat is that the system I am using has 16bit addresses. So for efficiency reasons I don't want to use any types larger than uint16_t.
Given that you have up to 256 (16-bit) values to map, there are in principle many mappings you could use. If the keys to be supported are uncorrelated, however, then any algorithm to compute the mappings requires all 256 keys or functions of them as parameters. In comments, for example, the idea of a 256th-degree polynomial is discussed, and the parameters would there are the coefficients of the polynomial.
Now consider that since the mapping needs 256 parameters, it also will use all those parameters in some way. How, then, can something with these general characteristics be efficiently computable?
The best solution I see for uncorrelated keys is to put all the keys in an array, sort them, and use each key's index in the sorted array as the wanted hash value. (Thus the parameters are the keys themselves in this case.) You can compute those indices fairly efficiently by binary search. Supposing that you store the sorted array for the duration of the program, I don't think you can do any such computation much more efficiently than this, and it's simple enough that you can be confident of its correctness.
That assumes you know all the keys before you need to hash any of them. If that is not the case then at minimum you can use an unsorted array and a linear search (though there may be in-between approaches, too). A linear search may not seem particularly efficient, but it's unlikely to be worse on average than a purely arithmetic computation involving 256 parameters.