函数位于glibc源码中的../glibc-version/string/argz-create.c中,其作用是将Unix-style的参数数组argv转换成一个argz vector。
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;
函数的实现如下:
/* 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的方式应当如下:
char *argz = NULL;
size_t len;
argz_create(argv, &argz, &len);
stpcpy函数(__stpcpy)在/usr/include/string.h中进行声明。
源码位于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输出不显示的结果。