【问题标题】:Trouble understanding void arrays and using them in function calls无法理解 void 数组并在函数调用中使用它们
【发布时间】:2017-11-09 05:02:02
【问题描述】:

我正在尝试一个问题,它要求我创建一个名为 randSwap 的函数,该函数接受 2 个 void 指针数组,并且有 50% 的机会在 2 个数组之间交换相同索引的 2 个值。下面是我的代码,但是每当我去编译时,它都会给我几个错误讨论:

警告:初始化使指针从整数而不进行强制转换。

void *array1[4] = {3,4,2,5};

还有其他几个与数组 1 和 2 相关的内容。

当我运行程序时,array1 的值被破坏,产生一个大的单个整数,并且 array 2 两次都打印它的原始值。

我对使用 void 类型非常不熟悉,因为我认为这就是问题所在。

#include <stdio.h>

int randSwap(void *array1[], void *array2[], int length)
{
    static int numofswaps = 0;
    int value;
    int toswap;
    void *temp;


    value = rand() % 2;
    if(value == 2)
    {
        toswap = rand() % length;
        temp = array1[toswap];
        array1[toswap] = array2[toswap];
        array2[toswap] = temp;

        numofswaps++; 
    }

    return numofswaps;
}

int main(void)
{
    int i;
    void *array1[4] = {3,4,2,5};
    void *array2[4] = {6,3,7,4};
    int length = 4;
    int numofswaps;
    srand(time(NULL));

    printf("Array1\n");
    for(i=0; i<length; i++);
    {

        printf("%d\t", (int*)array1[i]);
    }

    printf("\nArray2\n");
    for(i=0; i<length; i++)
    {
        printf("%d\t", (int*)array2[i]);
    }

    numofswaps = randSwap(array1, array2, length);
    numofswaps = randSwap(array1, array2, length);

    printf("\nArray1\n");
    for(i=0; i<length; i++);
    {

        printf("%d\t", (int*)array1[i]);
    }

    printf("\nArray2\n");
    for(i=0; i<length; i++)
    {
        printf("%d\t", (int*)array2[i]);
    }
    printf("\n");
    return 0;
 }

【问题讨论】:

  • main 函数中声明例如array1 作为指向void 的指针数组,但您没有使用有效指针对其进行初始化?你真正想做什么?数组的目的是什么?为什么用int 值而不是指针来初始化它们?
  • *array1[4] 是一个 指针数组 [其中 4 个],= {3,4,2,5}; 是对 4 个 int 值的初始化。 (int值不等于指针)。
  • 问题要求我在函数 randSwap 中使用“空指针数组”作为参数。我不知道为什么......而且我不知道该怎么做。如果我只使用'array1 [4]',我会收到一个错误,上面写着'错误:array1 声明为空数组'。
  • @L.Kay 你需要决定你希望数组包含什么。如果元素是空指针,即void *,那么它们必须包含某种类型的指针。问题是,指向什么?这是您必须回答的问题。
  • 换句话说,声明int array1 = {3,4,2,5}..,然后将数组作为void * 传递给函数(然后您需要在取消引用之前强制转换函数——就像在qsort 比较中一样函数)

标签: c random void


【解决方案1】:

您的代码中有大量小问题。继续我的 cmets,您正尝试使用 4-int 值初始化 指针数组[4]。不要试图将array1array2 声明为无效,只需将它们声明为int[] 并将它们作为void* 传递给randSwap,例如

    int i,
        array1[] = {3, 4, 2, 5},
        array2[] = {6, 3, 7, 4},
        length = sizeof array1 / sizeof *array1,
        numofswaps = 0;

numSwaps 的下一个,您对modulo (%) 的使用减少了一个:

    value = rand() % 2;     /* produces value 0 - 1 */
    if (value == 2)         /* will never equal 2 */

您只需要测试01,例如

    value = rand() % 2;     /* produces value 0 - 1 */
    if (value)              /* either 0 or 1 */
    {
        ...

不要将numofswaps 声明为randSwap 中的static,而是将其声明为main() 中的简单int,并将其作为参数传递给randSwap

要处理numSwap 中作为void * 传递的数组,您需要在尝试访问它们的值之前将它们强制转换为int*,以避免尝试取消引用void 指针(不允许)。你可以做类似的事情:

int randSwap (void *array1, void *array2, int length, int ns)
{
    int value,
        toswap,
        temp,
        *a1 = (int*)array1, /* note: the explicit casts are optional, the */
        *a2 = (int*)array2; /* declaration of a1 & a2 as int* is sufficient */

    value = rand() % 2;     /* produces value 0 - 1 */
    // if (value == 2)         /* will never equal 2 */
    if (value)              /* either 0 or 1 */
    {
        toswap = rand() % length;
        temp = a1[toswap];
        a1[toswap] = a2[toswap];
        a2[toswap] = temp;

        ns++; 
    }

    return ns;
}

ns代表numofswaps——我不喜欢打字……)

将所有部分放在一起,您可以将代码重新编写为类似于以下内容:

#include <stdio.h>
#include <stdlib.h> /* for rand() and srand() */
#include <time.h>   /* for time() */

int randSwap (void *array1, void *array2, int length, int ns)
{
    int value,
        toswap,
        temp,
        *a1 = array1,
        *a2 = array2;

    value = rand() % 2;     /* produces value 0 - 1 */
    // if (value == 2)         /* will never equal 2 */
    if (value)              /* either 0 or 1 */
    {
        toswap = rand() % length;
        temp = a1[toswap];
        a1[toswap] = a2[toswap];
        a2[toswap] = temp;

        ns++; 
    }

    return ns;
}

int main (void)
{
    int i,
        array1[] = {3, 4, 2, 5},
        array2[] = {6, 3, 7, 4},
        length = sizeof array1 / sizeof *array1,
        numofswaps = 0;

    srand(time(NULL));

    printf ("Array1\n");
    for (i = 0; i < length; i++)
        printf (" %d", array1[i]);

    printf("\nArray2\n");
    for (i = 0; i < length; i++)
        printf (" %d", array2[i]);

    numofswaps = randSwap (array1, array2, length, numofswaps);
    numofswaps = randSwap (array1, array2, length, numofswaps);

    printf ("\nArray1\n");
    for (i = 0; i < length; i++)
        printf (" %d", array1[i]);

    printf ("\nArray2\n");
    for (i = 0; i < length; i++)
        printf(" %d", array2[i]);

    // putchar ('\n');     /* don't printf a single-character */
    printf ("\n\nnumber of swaps: %d\n", numofswaps);

    return 0;
}

注意:你没有在main()输出numofswaps,我在最后给你加了)

使用/输出示例

 $ ./bin/ptrswap
Array1
 3 4 2 5
Array2
 6 3 7 4
Array1
 6 4 2 5
Array2
 3 3 7 4

number of swaps: 1

作为对randSwap 的进一步改进,无需将numofswaps 声明为static,也无需将其作为参数传递。您需要做的就是让randSwap 返回01 以指示是否发生了交换并将交换汇总回main(),例如

int randSwap (void *array1, void *array2, int length)
{
    int toswap, temp,
        *a1 = array1,
        *a2 = array2;

    if (rand() % 2) {   /* either 0 or 1 */
        toswap = rand() % length;
        temp = a1[toswap];
        a1[toswap] = a2[toswap];
        a2[toswap] = temp;

        return 1;
    }

    return 0;
}

然后在main()

    if (randSwap (array1, array2, length))
        numofswaps++;
    if (randSwap (array1, array2, length))
        numofswaps++;

注意:这是更简洁的处理方式——相同的输出)

查看一下,如果您还有其他问题,请告诉我。

【讨论】:

  • void** 是不必要的,我重做只是交换 int。如果交换指针是一项硬性要求,那么您仍然可以通过void *,但转换的处理方式会有所不同。 -- 上面的代码中没有UB。这只是避免字面意思创造力的另一种方法。
  • 哦,抱歉,我错过了您还更改了 randSwap 函数的声明。如果问题允许声明的灵活性,我认为这是可以的。
  • 没问题。我考虑过初始化一个指向int 数组元素的指针数组,但这确实使场景过于复杂。提问者可能想要交换指针,但考虑到问题和问题的级别,我怀疑要求是将int 数组作为void* 传递并处理交换。
  • 同意。 OP可能以错误的方式解释了这个问题。无论如何,标准 qsort 也以同样的方式做到这一点。
  • (ns representing numofswaps -- I don't like typing...),但是你输入了所有内容:^)
【解决方案2】:

您要做的是用整数数组初始化void 指针数组

   void *array1[4] = {3,4,2,5};

本质上是试图将一个整数分配给一个指针。因此警告 -

警告:初始化使指针从整数而不进行强制转换。

Rest 警告可能是因为这些变量的声明不正确。现在,您在 cmets 中提到问题要求您使用这种类型定义函数 randSwap。这可能是因为他们想要一个通用界面。

所以你可以做的是,让你的数组也包含指向整数的指针 -

void *array1[4] = {&(int){3}, &(int){4}, &(int){2}, &(int){5}};

这将创建int 文字,您可以获取它们的地址。

您还必须将您的 printf 更改为 -

printf("%d\n", *(int*)array1[i]); // Add * to dereference the pointer. 

这将使您的代码正常工作。

最后,我在您的代码中看到了一些其他错误 -

for(i=0; i<length; i++);

这会将i 的值设置为4,并最终在下一行进行越界访问。

你可能需要

for(i=0; i<length; i++)

【讨论】:

  • 关于“分配数组”的措辞:数组不能在C中分配。OP的代码是什么正在做的事情叫做“初始化一个数组”。
  • @alk for 循环的末尾有一个;。它所做的就是将i 设置为len
猜你喜欢
  • 1970-01-01
  • 2022-11-12
  • 2021-11-22
  • 1970-01-01
  • 2018-08-01
  • 2021-03-04
  • 1970-01-01
  • 2022-08-06
  • 1970-01-01
相关资源
最近更新 更多