函数位于glibc源码中的../glibc-version/string/argz-create.c中,其做用是将Unix-style的参数数组argv转换成一个argz vector。linux
argz vector是存储在连续空间的一维字符数组,彼此之间以空字符(\0)进行分隔。数组
也就是说argz_create函数的目的是将二维的argv转换成一维数组,而且内容不变,保留\0做为字符串之间的分隔符。函数
函数声明以下:测试
// argz.h /* Make a '\0' separated arg vector from a unix argv vector, returning it in ARGZ, and the total length in LEN. If a memory allocation error occurs, ENOMEM is returned, otherwise 0. The result can be destroyed using free. */ extern error_t __argz_create (char *const __argv[], char **__restrict __argz, size_t *__restrict __len) __THROW; extern error_t argz_create (char *const __argv[], char **__restrict __argz, size_t *__restrict __len) __THROW;
函数的实现以下:unix
/* Make a '\0' separated arg vector from a unix argv vector, returning it in ARGZ, and the total length in LEN. If a memory allocation error occurs, ENOMEM is returned, otherwise 0. */ error_t __argz_create (char *const argv[], char **argz, size_t *len) { int argc; size_t tlen = 0; char *const *ap; char *p; for (argc = 0; argv[argc] != NULL; ++argc) tlen += strlen (argv[argc]) + 1; if (tlen == 0) *argz = NULL; else { *argz = malloc (tlen); if (*argz == NULL) return ENOMEM; for (p = *argz, ap = argv; *ap; ++ap, ++p) p = __stpcpy (p, *ap); } *len = tlen; return 0; } weak_alias (__argz_create, argz_create)
须要注意的是,char *argv[]是main函数参数中的二维数组,它是以NULL做为结束标志的,即argv[argc]=NULL,因此程序能够使用argv[argc] != NULL进行判断,而普通的二维数组是不符合这一特色的。由此,程序能够求得整个argv(包括\0在内)在一维上的长度。指针
调用argz_create的方式应当以下:rest
char *argz = NULL; size_t len; argz_create(argv, &argz, &len);
stpcpy函数(__stpcpy)在/usr/include/string.h中进行声明。code
源码位于glibc源码中的../glibc-version/string/stpcpy.c文件中。字符串
具体定义以下:源码
/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */ char *__stpcpy (char *dest, const char *src) { size_t len = strlen (src); return memcpy (dest, src, len + 1) + len; }
正如注释中所说,stpcpy函数返回的是返回指向dest结尾处字符('\0')的指针。
注意:stpcpy函数不是标准库中的函数,只有glibc中有。
写个程序测试一下:
/* Windows(R) 7, Ultimate edition CodeBlocks13.12 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define ENOMEM 12 #ifndef __error_t_defined typedef int error_t; #endif /* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */ char *__stpcpy (char *dest, const char *src) // linux系统中能够不添加该函数 { size_t len = strlen (src); return memcpy(dest, src, len + 1) + len; } error_t __argz_create(char *const argv[], char **argz, size_t *len) { int argc; size_t tlen = 0; char *const *ap; char *p; for (argc = 0; argv[argc] != NULL; ++argc){ tlen += strlen (argv[argc]) + 1; } if (tlen == 0) *argz = NULL; else { *argz = malloc(tlen); if (*argz == NULL) return ENOMEM; for (p = *argz, ap = argv; *ap; ++ap, ++p) p = __stpcpy (p, *ap); } *len = tlen; return 0; } int main(void) { int i; char *argv[6] = { "vector creating using these fu", "nctions may be fre", "ed by using free; conversely, any argz", "function that may grow a ", "string expects that string to have been all", NULL }; char *argz = NULL; size_t len; if(__argz_create(argv, &argz, &len)){ printf("error!\n"); return 1; } for(i=0; i<len; ++i){ putchar(argz[i]); } putchar('\n'); return 0; }
程序输出以下:
注意,输出结果中字符串之间的“空格”并非空格,而是\0输出不显示的结果。