当您可以直接将指针传递给C函数时,为什么要使用memcpy()?

阿维纳尔

这是BCrypt文件加密实用程序源代码的一部分。不变,除了我添加的一些评论。

uLong BFEncrypt(char **input, char *key, uLong sz, BCoptions *options) {
  uInt32 L, R;
  uLong i;
  BLOWFISH_CTX ctx;
  int j;
  unsigned char *myEndian = NULL;
  j = sizeof(uInt32);

  getEndian(&myEndian);

// makes space 2 bytes
  memmove(*input+2, *input, sz);

// add endian and compresssion option
  memcpy(*input, myEndian, 1);
  memcpy(*input+1, &options->compression, 1);

  sz += 2;    /* add room for endian and compress flags */ // total size increased

  Blowfish_Init (&ctx, key, MAXKEYBYTES); // initialize 

// encrypt the file
  for (i = 2; i < sz; i+=(j*2)) {   /* start just after tags */
    memcpy(&L, *input+i, j);// copy j bytes from input to L
    memcpy(&R, *input+i+j, j); // copy second j byte to R
    Blowfish_Encrypt(&ctx, &L, &R); // encrypt
    memcpy(*input+i, &L, j); // copy everything back
    memcpy(*input+i+j, &R, j);
  }

  if (options->compression == 1) {
    if ((*input = realloc(*input, sz + j + 1)) == NULL)
      memerror();

    memset(*input+sz, 0, j + 1);
    memcpy(*input+sz, &options->origsize, j);
    sz += j;  /* make room for the original size      */
  }

  free(myEndian);
  return(sz);
}

在循环中,我们首先将文件缓冲区逐字节复制到新变量,然后应用河豚加密。然后再次将字节复制到缓冲区。为什么不能将字节直接传递给加密函数?为什么memcpy()甚至需要?

埃里克·波斯蒂奇

为什么不能将字节直接传递给加密函数?

有两个反对或至少不支持它的规则。

第一个是如果对的对齐方式不正确,则将char指针转换为指向的指针int具有未定义的行为int,并且即使对齐方式正确,结果的值也未完全定义。有关此规则,请参见C 2018 6.3.2.3,其中涉及指针转换。

通常,诸如之类的对象int必须位于四个字节的倍数处。这是因为计算机内存和数据总线的组织方式;所涉及的各种“电线”被设置为以一定大小和排列的组来传输事物。当此类系统的编译器生成用于处理int对象的指令时,它会生成加载对齐单词的指令。如果您使用char未对齐的指针并将其转换为的指针int,则当加载对齐字指令尝试使用未对齐的地址时,某些处理器将生成陷阱。其他处理器可能会忽略地址的低位,并从其他地址加载对齐的字。

即使地址对齐,C标准也不能保证将a转换char *int *实际指向与原始位置相同的位置的结果。这是因为在某些系统中(现在大多是过时的),以不同的方式表示了指向不同类型的指针。有些系统仅以多个字节为单位访问内存,因此,要实现该功能char *,编译器必须合成与硬件地址不同的地址,而对于而言int *,编译器可能会直接使用硬件地址。

第二条规则是,指定用于一种类型(例如的数组)的内存char不能随意地用作另一种类型(例如)的内存int此规则在C 2018 6.5 7中。它具有允许的特定情况,例如,可以将任何类型(例如int或)float作为进行访问char,反之亦然。该规则的目的是使例程可以通过anint *i和afloat *f在这样的代码中知道这一点:

for (int j = 0; j < 1024; ++j)
    f[j] += *i;

f[j]总访问float,从不访问的int,所以这个循环体永远不会改变的价值*i这意味着编译器可以优化代码以:

int t = *i;
for (int j = 0; j < 1024; ++j)
    f[j] += t;

*i由于临时对象t可以保存在处理器寄存器中,因此可以节省从内存重复加载的工作(最重要的是,编译器实际上可以使用float t = *i;,保存*i从内存的重复加载和向的重复转换,以节省float添加的时间。)

您可能会查看该动机,然后查看Blowfish_Encrypt并看到它BlowFish_Encrypt永远不会从这种潜在的优化中受益,可能是因为它从未与受此规则影响的混合类型一起运行。但是,随着编译器在转换中变得越来越先进和积极,编译器优化的复杂性变得越来越难以看到,因此很容易错过编译器从将一种类型别名为另一种类型的规则中将获得的某些优势。无论如何,由于存在该规则,因此您无法保证程序会在违反该规则的情况下运行。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

当您可以直接将变量作为指针指向时,为什么要在C中创建指针?

来自分类Dev

当您可以在 Javascript 中全局调用函数时,为什么要使用回调?

来自分类Dev

在C语言中,为什么我可以将函数名称(而不是指针)作为参数传递给函数?

来自分类Dev

当单指针可以在Objective-C中工作时,为什么要使用双指针?

来自分类Dev

为什么将“this”指针直接传递给存档错误,但另一个相同类型的指针可以?

来自分类Dev

当可以直接访问对象属性时,为什么要使用函数来获取它?

来自分类Dev

为什么在声明使用命名空间std时将int用作指针参数传递给函数?

来自分类Dev

为什么可以将未初始化的变量地址传递给函数的指针参数

来自分类Dev

C ++:为什么我可以将指针值成员变量从const成员函数传递给采用非const指针参数的外部函数?

来自分类Dev

将数组传递给函数时要使用的正确模式

来自分类Dev

C++ 可以将空指针传递给函数吗?

来自分类Dev

为什么将指针传递给具有常量指针类型参数的函数时不需要类型转换?

来自分类Dev

C ++:将指针的指针传递给函数

来自分类Dev

c:将2D数组传递给函数并使用辅助函数时的指针错误

来自分类Dev

将指针传递给函数时C ++崩溃

来自分类Dev

将字符串直接传递给C中输入参数为char指针的函数的潜在问题是什么?

来自分类Dev

我们可以直接将值分配给任何数据成员。为什么要使用构造函数?

来自分类Dev

您可以将函数参数结构传递给函数吗?

来自分类Dev

当您可以导入Java类时,为什么要使用依赖注入?

来自分类Dev

当您可以在.js文件中进行设置时,为什么还要使用.env文件?

来自分类Dev

当您可以通过POST执行所有操作时,为什么还要使用REST API?

来自分类Dev

在 Python 中,为什么当我将列表传递给函数时,我不能直接更改它?

来自分类Dev

C ++,为什么可以将rvalue传递给以lvalue引用为参数的函数

来自分类Dev

您可以通过什么方式将参数传递给JavaScript中的函数?

来自分类Dev

为什么将指针传递给函数作为值时,Go不会报告编译错误?

来自分类Dev

为什么将指针指向字符串传递给函数时出现2个星标

来自分类Dev

使用cgo将函数指针传递给C代码

来自分类Dev

C ++直接将数组传递给函数

来自分类Dev

为什么将额外的参数传递给C函数不会导致编译时错误?

Related 相关文章

  1. 1

    当您可以直接将变量作为指针指向时,为什么要在C中创建指针?

  2. 2

    当您可以在 Javascript 中全局调用函数时,为什么要使用回调?

  3. 3

    在C语言中,为什么我可以将函数名称(而不是指针)作为参数传递给函数?

  4. 4

    当单指针可以在Objective-C中工作时,为什么要使用双指针?

  5. 5

    为什么将“this”指针直接传递给存档错误,但另一个相同类型的指针可以?

  6. 6

    当可以直接访问对象属性时,为什么要使用函数来获取它?

  7. 7

    为什么在声明使用命名空间std时将int用作指针参数传递给函数?

  8. 8

    为什么可以将未初始化的变量地址传递给函数的指针参数

  9. 9

    C ++:为什么我可以将指针值成员变量从const成员函数传递给采用非const指针参数的外部函数?

  10. 10

    将数组传递给函数时要使用的正确模式

  11. 11

    C++ 可以将空指针传递给函数吗?

  12. 12

    为什么将指针传递给具有常量指针类型参数的函数时不需要类型转换?

  13. 13

    C ++:将指针的指针传递给函数

  14. 14

    c:将2D数组传递给函数并使用辅助函数时的指针错误

  15. 15

    将指针传递给函数时C ++崩溃

  16. 16

    将字符串直接传递给C中输入参数为char指针的函数的潜在问题是什么?

  17. 17

    我们可以直接将值分配给任何数据成员。为什么要使用构造函数?

  18. 18

    您可以将函数参数结构传递给函数吗?

  19. 19

    当您可以导入Java类时,为什么要使用依赖注入?

  20. 20

    当您可以在.js文件中进行设置时,为什么还要使用.env文件?

  21. 21

    当您可以通过POST执行所有操作时,为什么还要使用REST API?

  22. 22

    在 Python 中,为什么当我将列表传递给函数时,我不能直接更改它?

  23. 23

    C ++,为什么可以将rvalue传递给以lvalue引用为参数的函数

  24. 24

    您可以通过什么方式将参数传递给JavaScript中的函数?

  25. 25

    为什么将指针传递给函数作为值时,Go不会报告编译错误?

  26. 26

    为什么将指针指向字符串传递给函数时出现2个星标

  27. 27

    使用cgo将函数指针传递给C代码

  28. 28

    C ++直接将数组传递给函数

  29. 29

    为什么将额外的参数传递给C函数不会导致编译时错误?

热门标签

归档