RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 768083
Accepted
Егор Филатов
Егор Филатов
Asked:2020-01-09 01:25:17 +0000 UTC2020-01-09 01:25:17 +0000 UTC 2020-01-09 01:25:17 +0000 UTC

对代码的误解

  • 772

我遇到了一个我有几个问题的代码,如果你回答,我将不胜感激

#include <stdio.h>
#include <stdlib.h>

int isOdd(int a) {
    return (a % 2 != 0);
}

unsigned int filter(int *arr, unsigned size, int (*pred)(int), int** out) {
    unsigned i;
    unsigned j;
    *out = (int*) malloc(sizeof(int)*size);
    for (i = 0, j = 0; i < size; i++) {
        if (pred(arr[i])) {
            (*out)[j] = arr[i];
            j++;
        }
    }
    *out = (int*) realloc(*out, j*sizeof(int));
    return j;
}

int main () {
    int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    unsigned i;
    unsigned size;
    int *aOdd = NULL;

    size = filter(a, 10, isOdd, &aOdd);
    for (i = 0; i < size; i++) {
        printf("%d ", aOdd[i]);
    }

}

问题 #1:为什么需要这种显式转换?

*out = (int*) malloc(sizeof(int)*size);
*out = (int*) realloc(*out, j*sizeof(int));

如果我没记错的话,它们是多余的。

问题 #2:我用感叹号突出显示的行中发生了什么?

    unsigned int filter(int *arr, unsigned size, int (*pred)(int), int** out) {
    unsigned i;
    unsigned j;
    *out = (int*) malloc(sizeof(int)*size); /* !!!!!!!!!! */
    for (i = 0, j = 0; i < size; i++) {
        if (pred(arr[i])) {
            (*out)[j] = arr[i]; /* !!!!!!!!!! */
            j++;
        }
    }
    *out = (int*) realloc(*out, j*sizeof(int)); /* !!!!!!!!!! */
    return j;
}

问题#3:以这种方式实现问题#2中的函数会不会更容易(仅通过指针,而不是通过指向指针的指针)

unsigned int filter(int *arr, unsigned size, int (*pred)(int), int* out) {
    unsigned i;
    unsigned j;
    for (i = 0, j = 0; i < size; i++) {
        if (pred(arr[i])) {
            *(out + j) = arr[i];
            j++;
        }
    }

    return j;
}

问题#2 中的功能和问题#3 中的功能之间是否存在显着差异甚至优势?

c
  • 3 3 个回答
  • 10 Views

3 个回答

  • Voted
  1. Best Answer
    Croessmah stands with Russia
    2020-01-09T01:42:55Z2020-01-09T01:42:55Z

    问题 #1:为什么需要这种显式转换?

    C 不需要。对于 C++,它们是必要的,因为 在 C++ 中,不允许从 void* 进行隐式转换。

    问题 #2:我用感叹号突出显示的行中发生了什么?

    1) 大小整数的内存分配。
    2)将满足谓词的元素复制到新分配的数组中。
    3) 截取一块未填充的数据数组

    问题#3:从问题中实现功能不是更容易吗

    他们给出不同的结果。

    问题#2 中的功能和问题#3 中的功能之间是否存在显着差异甚至优势?

    对于问题 #2 的变体,内存直接在函数中分配,然后被截断。对于第三个问题选项,这个责任将落在调用者身上。两种方法都有优点和缺点。这完全取决于您如何使用它们。

    • 6
  2. AnT stands with Russia
    2020-01-09T03:32:16Z2020-01-09T03:32:16Z

    我之前已经写过这个。当您实现一个结果数组大小事先不知道的函数时,即 只有在函数内部才知道,那么就会出现分配正确数量的内存来存储结果的问题。

    用户(即调用代码)一般不能提前分配这块内存,因为他还不知道需要多少内存。在这种情况下,有几个主要策略:

    1. 在某些情况下,结果的最大可能大小是预先知道的,可以预先“最大限度地”分配内存,这样的最大分配在有条件的情况下是“合理的”。

      这只是你的情况。是的,你的#3 可以很好地使用这种模式。用户只需要至少提供一个大小的输出数组,size并记住通常不会使用所有数组。

    2. 在函数内部分配内存:当它的大小变得已知时立即分配内存,或者随着结果的累积而递增,或者在随后的截断中“最大”,或者其他什么。

      这是您的#2 选项。

      这种方法的问题在于,这种情况下的内存分配不容易定制。在最简单的情况下,malloc就像您的示例一样。也许用户不需要它malloc?

    3. 实现 image 和 likeness 中的功能snprintf,即 提供“虚拟”传递的可能性,该传递仅计算并返回结果的大小,但尚未生成结果。

      收到计算的大小后,用户以任何方便的方式分配内存,然后再次调用相同的函数,这次是“真正的”传递,即 在缓冲区中形成结果。

    也就是说,您的 #2 和 #3 是解决问题的两种替代方法。这两种方法在他们自己的方式上都是正确的。

    • 2
  3. Andrej Levkovitch
    2020-01-09T01:58:54Z2020-01-09T01:58:54Z

    除了 Groessmah 的回答之外,我将对第三个问题进行澄清:

    您的函数实现错误:首先,没有内存分配 - 您的指针仍然指向NULL! 为了在函数中分配内存,你需要一个指向指针的指针,否则你可以分配内存,但是他们会让我们需要的指针指向它——不。其次,如果我们在调用函数之前分配内存,在函数中切割它,同样是行不通的。

    • 1

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5