我正在使用函数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++;
}
如果不可能,因为“没有这个变量的地址”:函数如何工作返回变量而不是指向变量的指针?
答案 0 :(得分:2)
仅讨论一个变量缓冲区
我认为你正在做错误的微优化。
正如 Uchia Itachi 指出的那样,获取返回值的地址将是一个错误。
实际上,如果您担心效率,那么瓶颈就是静态存储。 malloc()具有内存开销 - 除了存储在静态内存中的数据外,还会写入元数据。例如,here (scroll down to Implementation Details)解释了一个聪明的最小算法如何为每个分配只有size_t的开销。这甚至不考虑分裂。
memcpy()是一个快速函数,但对于单个数字也是一种过度杀伤。
因此,我建议仅使用堆栈。使buff成为全局整数变量。然后将buff,s地址传递给那些,需要一个缓冲区。他们不会注意到差异。
讨论修改过的问题 - 循环中有大量写入和读取的大缓冲区
当函数返回(某物)时,它会将值(或指向对象的指针)推送到寄存器或堆栈中。另一方面,当声明,初始化和使用变量时,它驻留在寄存器或堆栈中。
你注意到相似之处吗?优化编译器删除不需要的变量,它们还创建未命名的变量供内部使用。例如,在检测到此范围内不再引用变量后,将重用存储变量。
因此,应该努力编写简单易读的代码,并将详细信息留给编译器。这意味着你的第二个例子非常好。
答案 1 :(得分:0)
您无法确定函数的返回值将放在何处。有时,值会在堆栈上返回,有时则可能在寄存器中。返回内容与在C中返回指针之间没有真正的区别。但是不要混淆仅在不同函数中定义和访问的局部变量。这样做会增加seg故障的可能性。此外,使用&amp; nbo并不浪费内存。
答案 2 :(得分: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);