I see many factors that make C programming uncomfortable for MS-DOS development:
- Many of the interface MS-DOS offered was targeted at assembly language anyway, like direct use of AX-DX registers to pass arguments and replies to system calls
- direct use of the (software) interrupts to call system services
- use of the 'carry flag' to report error during system calls, which can be efficiently set/cleared/tested at assembly level and is missing from the C programming model altogether.
- all of the above also applies to calls to the BIOS functions that the MS-DOS will have to do to use low-level "drivers".
- it has to run real mode programs, which had to split code among multiple segments. The C execution environment model assumes one segment for the code and one for stack+data. C compilers of the era had complex behaviour to emulate that, sometimes by restricting the program to 64K. As a service to third-party software, MS-DOS must be able to work with buffers/strings located anywhere, forcing it to use exotic FAR pointers and the like all over the code.
Later versions of MS-DOS will still be facing the same constraints about BIOS, established interfaces and real mode addressing, so assembly might still be preferable over C for them.