同时替换多个字符

Replacing multiple chars at the same time

本文关键字:字符 替换      更新时间:2023-10-16

所以在我的代码中,我有一系列的字符,我想用随机数据替换它们。由于 rand 可以替换 int,我想我可以通过一次替换四个字符而不是一次替换一个来节省一些时间。所以基本上不是这个:

  unsigned char TXT[] = { data1,data2,data3,data4,data4,data5....
  for (i = 34; i < flenght; i++) // generating the data to send.
     TXT[i] = rand() % 255;

我想做这样的事情:

unsigned char TXT[] = { data1,data2,data3,data4,data4,data5....
for (i = 34; i < flenght; i+4) // generating the data to send.
  TXT[i] = rand() % 4294967295;

效果很好,但我不确定后半部分该怎么做。非常感谢您能给我的任何帮助,谢谢!

那行不通。编译器将从rand() % big_number中获取结果,并切掉多余的数据以使其适合unsigned char

在速度方面,您最初的方法很好。您考虑的优化是有效的,但很可能不需要。这可能不会产生明显的差异。

当然,你想做的事情可能的,但考虑到你的错误,我想说的是,理解现在的努力远远超过了好处。继续学习,下次你遇到这样的代码时,你会知道该怎么做(并判断是否有必要(,回顾这一刻并:)微笑。

您必须直接访问内存,并对数据进行一些转换。你可能想要这样的东西:

unsigned char TXT[] = { data1,data2,data3,data4,data4,data5....
for (i = 34; i < flenght/sizeof(int); i+=sizeof(int)) // generating the data to send.
{
     int *temp = (int*)&TXT[i]; // very ugly
     *temp = rand() % 4294967295;
}

由于对齐问题,这可能会有问题,所以要小心。对齐问题可能会导致程序意外崩溃,并且难以调试。如果我是你,我不会这样做,你的初始代码很好。

 TXT[i] = rand() % 4294967295;

不会按预期方式工作。也许您期望rand()%4294967295将生成一个 4 字节整数(您可能会将其解释为 4 个不同的字符(。rand()%4294967295产生的值将被类型转换为单个字符,并且将仅分配给TXT[i]索引之一。

虽然不清楚为什么需要同时进行 4 个赋值,但一种方法是使用位运算符来获取生成的数字的 4 个不同的有效字节,然后可以将这些字节分配给四个不同的索引。

这么多有效的答案 C 不太关心它存储在哪个地址的类型。因此,您可以侥幸逃脱以下情况:

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

char *arr;
int *iArr;

int main (void){
  int i;
  arr = malloc(100);
  /* Error handling ommitted, yes that's evil */
  iArr = (int*) arr;
  for (i = 0; i < 25; i++) {
   iArr[i] = rand() % INT_MAX;
  }
  for (i = 0; i < 25; i++) {
   printf("iArr[%d] = %dn", i, iArr[i]);
 }
for (i  = 0; i < 100; i++) {
  printf("arr[%d] = %cn", i, arr[i]);
}
free(arr);
return 0;
}

最后,数组只是内存中的某个连续块。您可以随心所欲地解释它(如果您愿意(。如果你知道 sizeof(int( = 4 * sizeof(char(,那么上面的代码就可以工作了。

不是说我推荐它。其他人指出,无论发生什么,通过 TXT 中所有字符的第一个循环都会产生相同的结果。例如,人们可以考虑展开一个循环,但实际上我不会在乎这一点。

(int*(本身就足够警告了。这意味着对编译器来说,不要考虑你认为的类型只是"相信"他程序员他知道得更多。

好吧,这种"知道得更好"可能是C编程中万恶之源。

unsigned char TXT[] = { data1,data2,data3,data4,data4,data5....
for (i = 34; i < flenght; i+4)
    // generating the data to send.
    TXT[i] = rand() % 4294967295;

这有几个问题:

  • TXT 不能保证 CPU 写入int数据所需的内存对齐(它是否工作 - 也许相对较慢 - 或不工作 - 例如 Solaris 上的 SIGBUS - 特定于硬件(
  • 最后 1-3 个字符可能会丢失(即使您将i + 4更改为 i += 4 ;-P(
  • 无论如何,rand()都会返回一个int - 你不需要用任何东西修改它
  • 您需要通过int*写入随机数据,以便一次访问 4 个字节,而不是简单地从随机数据的末尾切出一个字节并覆盖每四个字符
  • 对于像这样依赖于int大小的东西,你真的应该用sizeof(int)来写它,这样即使int不是32位也可以工作,或者使用(目前可悲的(非标准但常见的typedef,例如int32_t(或者在Windows上我认为它是__int32,或者你可以使用boost或其他库头来获取int32_t, 或编写自己的typedef(。

对齐文本数据实际上非常棘手:您的代码建议您想要从第 35 个字符开始int大小的切片......即使整体字符数组与整数正确对齐,第 35 个字符也不会对齐。

如果它确实始终是第 35 个,那么您可以使用前导字符填充数据,以便访问第 36 个(可能是 32 位int大小的倍数(,然后将文本对齐到 32 位地址(使用特定于编译器的#pragma或使用与 int32_t 的并集(。 如果实际代码改变了您开始覆盖的字符,以至于您无法简单地对齐一次数据,那么您将陷入困境:

  • 您的原始字符一次覆盖
  • 非可移植的未对齐覆盖(如果可能且在您的系统上更好(,或
  • 实现最多覆盖三个
  • 前导未对齐字符的代码,然后切换到对齐地址的 32 位整数覆盖模式,然后返回到最多三个尾随字符的逐字符覆盖。

这不起作用,因为生成的值被转换为数组元素的类型 - char在这种特殊情况下。但是,您可以按照自己喜欢的方式自由解释分配的内存。例如,您可以将其转换为数组int

unsigned char TXT[] = { data1,data2,data3,data4,data4,data5....
for (i = 34; i < flenght-sizeof(int); i+=sizeof(int)) // generating the data to send.
    *(int*)(TXT+i) = rand(); // There is no need in modulo operator
for (; i < flenght; ++i) // generating the data to send.
    TXT[i] = rand(); // There is no need in modulo operator either

我只想用关于模运算符和数组处理而不是sizeof(int)倍数的评论来完成解决方案。

1( %的意思是"除以时的余数",所以你想要rand() % 256字符,否则你永远不会得到值为 255 的字符。与 int 情况类似,尽管在这里无论如何都没有必要进行模运算,因为您想要整个输出值范围。

2(rand通常一次只生成两个字节;检查 RAND_MAX 的值。

3(反正34不能被4整除,所以你必须专门处理最终情况。

4(您将需要投射指针,如果它尚未对齐,它将不起作用。但是,一旦有了强制转换,就不需要考虑迭代中的sizeof(int):指针算术会自动处理元素大小。

5(很有可能它不会产生明显的差异。如果将随机数据写入数组确实是程序中的瓶颈,那么无论如何它都没有真正做任何有意义的事情。