Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
声明指向C字符串数组的指针时应该使用多少星号?_C_Dll_Vb6_Pointers_Reference - Fatal编程技术网

声明指向C字符串数组的指针时应该使用多少星号?

声明指向C字符串数组的指针时应该使用多少星号?,c,dll,vb6,pointers,reference,C,Dll,Vb6,Pointers,Reference,我有一个VB应用程序从C DLL请求用户列表: VB将询问DLL有多少用户,然后将数组初始化为适当的大小。 然后VB将通过引用将其数组传递给DLL函数,该函数将用用户名填充数组 我开始这样编写C函数:foo(char**bar)将被视为字符串数组。但后来我意识到,我将使数组中的每个项指向不同的C字符串(struct userlist链接列表中的char*username),而不是修改已经指向的数据。数组数组是按值传递的:一个地址列表的副本,因此地址指向原始数据,但修改该副本中的地址不会改变调用方

我有一个VB应用程序从C DLL请求用户列表:
VB将询问DLL有多少用户,然后将数组初始化为适当的大小。
然后VB将通过引用将其数组传递给DLL函数,该函数将用用户名填充数组

我开始这样编写C函数:
foo(char**bar)将被视为字符串数组。但后来我意识到,我将使数组中的每个项指向不同的C字符串(
struct userlist
链接列表中的
char*username
),而不是修改已经指向的数据。数组数组是按值传递的:一个地址列表的副本,因此地址指向原始数据,但修改该副本中的地址不会改变调用方的地址列表(我认为,无论如何)。所以,我应该声明它
foo(char***bar)?这将是一个指向字符串数组的指针,因此,如果我更改数组所指向的字符串,它将修改调用者(VB)正在使用的字符串数组……对吗

这是我到目前为止的用法(还没有测试过它…到目前为止,我仍在编写DLL,到目前为止还没有VB前端来调用它)

EXPORT void\u stdcall update\u用户列表(char***ulist){
int i=0;
userlist*cur\u user=userlist\u head;//指向链接列表中第一项的指针
对于(;i用户名;
当前用户=当前用户->下一步;
}
}

两个星号是正确的选择

char*   // is a pointer to a char
char**  // is a pointer to a char pointer
char*** // is a pointer to a pointer to a char pointer - e.g. multi-dimensional array (err...)

我把自己弄糊涂了:)

两个星号才是前进的方向

char*   // is a pointer to a char
char**  // is a pointer to a char pointer
char*** // is a pointer to a pointer to a char pointer - e.g. multi-dimensional array (err...)

我把自己弄糊涂了:)

一般来说,按照你的要求去做并不简单,因为VB不理解C风格的ASCIIZ字符串和数组

如果您的DLL不需要一个BSTR的VB安全数组,那么填充它会有一些困难

让VB通过引用第一个元素来传递Long(C int)数组是很简单的,您可以用指向单个字符串的指针来填充它。VB端可以将它们复制到VB字符串中。但在这种情况下,谁来处理C字符串,何时处理

如果您创建VB数组并用预先设置大小的字符串填充它,您仍然需要在C端处理SafeArray,因为您不能通过引用传递单个VB字符串数组元素,而期望在内存中找到与其相邻的其余字符串

最好、最安全的方法是让DLL创建一个所谓“ANSIBSTR”的安全数组,并在VB中将函数声明为返回字符串数组。这样就不需要两次调用,因为数组边界将说明整个过程

======编辑=====

当VB将一个字符串数组传递给一个声明的函数时,它会在幕后进行一些巫术操作。它首先将所有字符串从Unicode转换为通常称为“Ansi BSTR”的格式。对于C来说,它们看起来像并且可以作为ASCIIZ或LPSTR处理,除了不能以正常的C方式创建或延长它们之外,您只能填充它们。在C端,传递的数组看起来像ppSA(SAFEARRAY**)。Ansi BSTR是由SafeArray的pData成员引用的一系列指针

绝对不能从数组中传递单个字符串(作为char*),而期望在内存中找到与其相邻的其余字符串。您必须传递数组本身并使用SafeArray API(或SA结构的知识)对其进行操作

这就是为什么最好的选择是直接在DLL中完成这一切。使用SafeArrayCreate创建阵列,然后使用SysAllocStringByteLen创建Ansi BSTR,并将这些字符串(即BSTR,即4字节指针)放入阵列插槽中。返回时,VB执行巫术并将字符串转换为Unicode


在VB中,您的函数将被声明为返回字符串()。

一般来说,按照您的要求执行并不简单,因为VB不理解C风格的ASCIIZ字符串和数组

如果您的DLL不需要一个BSTR的VB安全数组,那么填充它会有一些困难

让VB通过引用第一个元素来传递Long(C int)数组是很简单的,您可以用指向单个字符串的指针来填充它。VB端可以将它们复制到VB字符串中。但在这种情况下,谁来处理C字符串,何时处理

如果您创建VB数组并用预先设置大小的字符串填充它,您仍然需要在C端处理SafeArray,因为您不能通过引用传递单个VB字符串数组元素,而期望在内存中找到与其相邻的其余字符串

最好、最安全的方法是让DLL创建一个所谓“ANSIBSTR”的安全数组,并在VB中将函数声明为返回字符串数组。这样就不需要两次调用,因为数组边界将说明整个过程

======编辑=====

当VB将一个字符串数组传递给一个声明的函数时,它会在幕后进行一些巫术操作。它首先将所有字符串从Unicode转换为通常称为“Ansi BSTR”的格式。对于C来说,它们看起来像并且可以作为ASCIIZ或LPSTR处理,除了不能以正常的C方式创建或延长它们之外,您只能填充它们。在C端,传递的数组看起来像ppSA(SAFEARRAY**)。Ansi BSTR是由SafeArray的pData成员引用的一系列指针

绝对不能从数组中传递单个字符串(作为char*),而期望在内存中找到与其相邻的其余字符串。您必须传递数组本身并使用SafeArray API(或SA结构的知识)对其进行操作

这就是为什么最好的选择是直接在DLL中完成这一切。使用SafeArrayCreate创建数组,然后使用SysAllocStringByteLen创建Ansi BSTR,并将这些字符串(即BSTR,即4字节指针)放入数组slo中
void update_userlist(char **ulist)
{
    int i = 0;
    userlist *cur_user = userlist_head;

    for(; i < usercount_; ++i)
    {
        ulist[i] = cur_user->username; // I am assuming that username is a char *
        cur_user = cur_user->next;
    }
}

// This sets up the array and calls the function.
char **mylist  = malloc(sizeof(char*) * usercount_);
update_userlist(mylist);