4

功能

我正在使用函数 uint32_t htonl(uint32_t hostlong) 将 uint32_t 转换为网络字节顺序。

我想做的事

将变量转换为网络字节顺序后,我需要对其进行计算:

//Usually I do calculate with much more variables and copy them into a much
// larger buff - to keep it understandable and simple I broke it down 
// to one calculation

uint32_t var = 1;
void* buff;

buff = malloc(sizeof(uint32_t));

while(var < 5) {
    var = htonl(var);
    memcpy(buff, &var, sizeof(uint32_t));
    doSomethingWithBuff(buff);
    var++; // FAIL
}

我能做的,但是...

其实我已经找到了解决这个问题的方法:

uint32_t var = 1, nbo;
void* buff;

buff = malloc(sizeof(uint32_t));

while(var < 5) {
    nbo = htonl(var);
    memcpy(buff, &nbo, sizeof(uint32_t));
    doSomethingWithBuff(buff);
    var++;
}

问题是我用这个解决方案浪费了内存,因为 nbo 只是用作缓冲区。

我更愿意做什么

如果我可以在 memcpy() 函数中使用 htonl() 函数就完美了。memcpy() 需要第二个值是 void*。我的问题是:如何获取 htonl() 的返回值的地址?

uint32_t var = 1;
void* buff;

buff = malloc(sizeof(uint32_t));

while(var < 5) {
    memcpy(buff, (GET ADDRESS)htonl(var), sizeof(uint32_t));
    doSomethingWithBuff(buff);
    var++;
}

如果因为“没有此变量的地址”而无法实现:返回变量而不是指向变量的指针的函数如何工作?

4

3 回答 3

2

只讨论一个变量缓冲区


我认为您正在做错误的微优化。

正如Uchia Itachi指出的那样,获取返回值的地址将是一个错误。

其实,如果你关心效率,瓶颈是静态存储。malloc() 有内存开销——除了存储在静态内存中的数据之外,还有元数据写入。例如,这里(向下滚动到实现细节)解释了一个聪明的最小算法如何对每个分配只有 size_t 的开销。这甚至没有考虑碎片化。

memcpy() 是一个快速函数,但对于单个数字来说也是一种过度杀伤力。

因此,我建议只使用堆栈。使 buff 成为全局整数变量。然后将 buff,s 地址传递给需要缓冲区的那些。他们不会注意到差异。

关于修改后的问题的讨论 - 循环中包含大量写入和读取的大缓冲区


当函数返回(某物)时,它会将值(或指向对象的指针)压入寄存器或堆栈中。另一方面,当一个变量被声明、初始化和使用时,它要么驻留在寄存器中,要么驻留在堆栈中。

你注意到相似之处了吗?优化编译器删除不需要的变量,它们还创建未命名的变量供内部使用。例如,在检测到该变量在此范围内不再引用后,将重用该变量的存储。

因此,应该努力编写简单易读的代码,并将细节留给编译器。这意味着您的第二个示例非常好。

于 2013-08-17T09:35:25.020 回答
0

您无法确定函数的返回值将放在哪里。有时,该值在堆栈中返回,有时,它可能在寄存器中。在 C 中返回一些东西和返回一个指针之间没有真正的区别。但是最好不要弄乱只能在不同函数中定义和访问的局部变量。这样做会增加出现段错误的机会。此外,使用 &nbo 也不会浪费内存。

于 2013-08-17T09:36:00.993 回答
0

您可以使用宏将问题“解决”:

#define APPEND_TO_BUFFER( \
  buffer, \
  value, \
  type) 
  { \
    type tmpvar = (value); \
    memcpy((buffer), &tmpvar, sizeof(type)); \
  }

...

char * buff = <some valid memory address>;

uint32_t var = <some value>;
int i = <some other value>;

...

  APPEND_TO_BUFFER(buff, htonl(var), uint32_t); /* Append converted var to buffer as per OP. */
  APPEND_TO_BUFFER(buff+sizeof(uint32_t), i, int); /* Append another i right after var.  */

  doSomethingWithBuff(buff);
于 2013-08-17T10:00:49.290 回答