Nada está errado. Está funcionando como pretendido. * redefine-se no início de cada hora / dia / mês. Colocado de outra forma, * é um substituto para o alcance máximo do valor em questão. Então * na coluna de minutos significa 0-59, e * / 40 significa "começando em 0, executado a cada 40 minutos até 59". Veja 'Caracteres especiais' na página do cron na Wikipédia para mais informações.
O que você provavelmente precisa fazer é executar o trabalho a cada 20 minutos e fazer com que o programa decida se deve ou não ser executado. Ou faça isso com duas linhas
0,40 0,2,4,6,8,10,12,14,16,18,20,22 * * * myshellcommand
20 1,3,5,7,9,11,13,15,17,19,21,23 * * * myshellcommand
Note que isso pode ser escrito de uma forma um pouco mais compacta:
0,40 */2 * * * myshellcommand
20 1-23/2 * * * myshellcommand
Neste caso, * / 2 indica cada segunda hora a partir de 0 (desde que * seja equivalente a 0-23) e 1-23 / 2 indica cada segunda hora a partir da hora 1.