argz_create函数

函数位于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输出不显示的结果。

相关文章
相关标签/搜索