Em "Programação Avançada no Ambiente UNIX" , W. Richard Stevens diz que é uma otimização de desempenho:
Ao especificar o descritor mais alto em que estamos interessados, o kernel pode evitar passar por centenas de bits não utilizados nos três conjuntos de descritores, procurando por bits que estão ativados.
(1ª edição, página 399)
Se você estiver fazendo algum tipo de programação de sistemas UNIX, o manual do APUE é altamente recomendado.
ATUALIZAR
Um fd_seté geralmente capaz de rastrear até 1024 descritores de arquivos.
A maneira mais eficiente para controlar quais fdsestão definidas para 0e que são definidas como 1seria uma bitset, de modo que cada fd_setconsistiria de 1024 bits.
Em um sistema de 32 bits, um int longo (ou "palavra") é de 32 bits, o que significa que cada um fd_seté
1024/32 = 32 palavras.
Se nfdsfor algo pequeno, como 8 ou 16, o que seria em muitas aplicações, ele precisa apenas olhar dentro da 1ª palavra, que deve ser claramente mais rápida do que dentro de 32.
(Veja FD_SETSIZEe __NFDBITSde /usr/include/sys/select.hpara os valores em sua plataforma.)
ATUALIZAÇÃO 2
Por que a assinatura da função não é
int select(fd_set *readfds, int nreadfds,
fd_set *writefds, int nwritefds,
fd_set *exceptfds, int nexceptfds,
struct timeval *timeout);
Meu palpite é que, porque o código tenta manter todos os argumentos nos registros , para que a CPU possa trabalhar neles mais rapidamente e, se tivesse que rastrear duas variáveis extras, a CPU talvez não tivesse registros suficientes.
Portanto, em outras palavras, selectestá expondo um detalhe de implementação para que seja mais rápido.