Processes on Linux and Windows are created differently, and arguments to process are passed differently as well.

Linux
Arguments passed via argv (an array of string; one string for one argument);
Process created via execve() API or alike:
int execve(const char *filename, char *const argv [], char *const envp[]);
Windows
Arguments passed via command line (a single string with all arguments combined);
Process created via CreateProcess() API:
int CreateProcess( ..., lpComandLine, ... )

If you are dealing with those APIs directly, things on Linux is much easier as no more escaping is needed; while on Windows, you need to escape command line carefully, so that it can be parsed into argv by the target program correctly.

Note that the parsing from command line to argv on Windows is done by the target program, not the OS, so every single program may have different rules for parsing.

Generally, there are three sets of rules being used for different kinds of executables:

  1. .bat, .cmd files use batch escaping rules;
  2. .vbs, .js files which run through wscript.exe or cscript.exe use wscript!SplitCommandLine();
  3. .exe files use CommandLineToArgvW;

For details on these rules, follow links given below.

If you are not dealing with those APIs that create process directly, but run commands through shell (bash, cmd.exe, etc.), then your input is first parsed by the shell, and next by create process related API.

Argv and Command Line Parsing Rules