- 理论
我有一组具有不同类型的变量S,并且我有一个指向内存地址的指针P,其大小为S.现在,我想将S的所有值分配给P然后再读回来。
这背后的重点是手动构建类似于结构的东西。
- 我做了什么:
让我们说我们有int i,char c和char * s作为我们的S
uint8_t* foo(int i, char c, char* s) {
uint8_t* r = malloc(sizeof(i) + sizeof(c) + sizeof(s));
*r = i;
*(r+sizeof(i)) = c;
*(r+sizeof(i)+sizeof(c)) = s;
return r;
}
int main(void) {
uint8_t * a = foo(500, 'a', "hello");
printf("%d, %c, %s\n", *a, *(a+sizeof(int)), (a+sizeof(int)+sizeof(char)) );
return 0;
}
这里的问题是我只将数据分配给第一个字节,然后只读取第一个字节。
- 问题:
如何告诉编译器foo on * r = i;将i分配给* r的下4个字节,然后将主读取* a分配为4个字节,然后对c和s执行相同的操作?
答案 0 :(得分:2)
我希望尽可能让计算机做数学计算。在这种情况下,我会使用struct
:
#include <stdio.h>
#include <stdlib.h>
struct multi_type {
int i;
char c;
char *s;
};
struct multi_type *foo(int i, char c, char *s) {
struct multi_type *result = malloc(sizeof(*result));
if (result == NULL) {
return NULL;
}
result->i = i;
result->c = c;
result->s = s;
return result;
}
int main(void) {
struct multi_type *a = foo(500, 'a', "hello");
if (a) {
printf("%d, %c, %s\n", a->i, a->c, a->s);
free(a);
}
return 0;
}
<强>输出强>
500, a, hello
此代码也更易于维护。如果struct multi_type
中的某个类型发生更改或我需要添加类型,则需要更改的代码更少。
答案 1 :(得分:1)
你必须施放你的左值,以便它们具有正确的类型:
uint8_t *foo(int i, char c, char *s) {
uint8_t *r = malloc(sizeof i + sizeof c + sizeof s);
*(int *)r = i;
*(char *)(r + sizeof i) = c;
*(char **)(r + sizeof i + sizeof c) = s;
return r;
}
为了阅读它们,还需要转换为适当的类型:
int main(void) {
uint8_t *a = foo(500, 'a', "hello");
printf("%d, %c, %s\n", *(int *)a, *(char *)(a + sizeof(int)), *(char **)(a + sizeof(int) + sizeof(char)));
return 0;
}
正如@chux在评论中指出的那样,这确实是未定义的行为。与以前一样,可以使用C11 _Alignof
运算符来获得符合标准的代码:
// Get the smallest multiple of _Alignof(type) >= off
#define GET_ALIGNED_OFFSET(off, type) ((off + _Alignof(type) - 1) / _Alignof(type) * _Alignof(type))
uint8_t *foo(int i, char c, char *s) {
size_t offset1 = GET_ALIGNED_OFFSET(sizeof i, char);
size_t offset2 = GET_ALIGNED_OFFSET(offset1 + sizeof c, char *);
uint8_t *r = malloc(offset2 + sizeof s);
*(int *)r = i;
*(char *)(r + offset1) = c;
*(char **)(r + offset2) = s;
return r;
}
虽然当然@David Cullen的答案仍然是从工程角度来看的最佳解决方案。