唯一的标准是设置optind = 1。
SUSv4 standard 没有提及optreset 并声明optind = 0“未指定”:
如果应用程序在调用getopt() 之前将optind 设置为零,则行为未指定。
否则,标准就含糊不清,根本没有说多次调用getopt(),既不允许也不声明未定义。
此外,没有定义说明是否支持optind = 0 或optreset(OpenBSD 支持前者,但 FreeBSD 不支持,Linux/musl 支持后者,但 Linux/glibc 不支持) ,所以没有任何可靠的方法可以通过#ifdefs 检测到它。
不是针对错误,在花哨的 getopt/_long 实现中(见下文),只需将 optind = 1 设置为重新启动 getopt(),只要
a)你没有使用任何GNU extensions:
扫描多个参数向量或重新扫描相同的程序
vector 不止一次,并希望使用 GNU 扩展,例如
+ 和 - 在 optstring 的开头,或更改
POSIXLY_CORRECT 在两次扫描之间,必须通过重置重新初始化 getopt()
optind 到 0,
b) 在它返回-1 之前,您不会在中间重新启动getopt()。例如。来自FreeBSD's getopt:
#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""
...
int
getopt(int nargc, char * const nargv[], const char *ostr)
{
static char *place = EMSG; /* option letter processing */
...
if (optreset || *place == 0) { /* update scanning pointer */
optreset = 0;
...
place = EMSG;
return (-1);
...
place = EMSG;
return (-1);
...
place = EMSG;
if (strchr(ostr, '-') == NULL)
return (-1);
...
return (BADCH);
...
return (BADARG);
...
return (BADCH);
...
return (optopt); /* return option letter */
}
错误
即使在返回-1 之后,getopt 的 glibc 实现也会cling to stale state。如果释放旧字符串,这可能会导致愚蠢的错误和崩溃。
OpenBSD 实现将执行likewise,但仅在使用虚假- 选项时,如getopt("q", ["prog", "-q-", NULL])。请注意,OpenBSD 的 getopt_long 实现可能已作为默认的 getopt() 进入其他系统,如 Solaris 和 Android。