如何通过指向结构中的松弛字节来访问另一个变量的数据?
How to access data of another variable by pointing to a slack-byte in a structure?
#include <stdio.h>
#include <stdlib.h>
struct someStruct {
int ivar;
char cvar;
float fvar;
};
main(argc,argv)
const char** argv;
{
struct someStruct someObj;
someObj.ivar = 1;
someObj.fvar = 2.3;
someObj.cvar = 'r';
printf("%u\n",&someObj.fvar);
printf("%u\n",(&someObj.cvar + 4));
printf("%f\n",*((&someObj.cvar) + 4));
printf("%f\n",someObj.fvar);
}
这是我编写的程序,它试图通过将 char 的地址加 4 来访问 fvar
的地址。
我知道松弛字节的概念。我试图访问那段记忆,瞧!它正确地打印了地址。
printf("%u\n",&someObj.fvar);
printf("%u\n",(&someObj.cvar + 4));
两者打印相同的地址。
然后我尝试通过以下方式访问fvar:
printf("%f\n",*((&someObj.cvar) + 4));
printf("%f\n",someObj.fvar);
和
0.000000
2.300000
是我的结果。
然后我意识到 char* 和 float* 的解释不同。
因此,我尝试了从 char* 到 float* 再到 float 以及从 char 到 float* 再到 float 的各种类型转换,并且在所有可能的点上都尝试过,例如 typecasting the returned address to float
,使用 4.0
而不是 4
(我意识到这不应该工作......但它没有),等等
不知何故,它只是不打印 2.300000
并继续打印 0.000000
我哪里漏掉了这个概念?
请注意,我有一个 64-bit MinGW
并添加了 slack-byte
(我知道有些人没有),我已经验证过:
printf("%u",sizeof(someObj.ivar));
printf("%u",sizeof(someObj.fvar));
printf("%u",sizeof(someObj.cvar));
printf("%u",sizeof(someObj));
分别产生 4
、4
、1
和 12 ....(sizeof(char) + 3)
。
P.S。我知道这是一个可怕的想法,但这是我通常学习概念的方式 XD
假设以下为真:
&someObj.cvar + 4 == &someObj.fvar
您可以将指针值转换为适当的类型:
printf("%f\n", *(float*)((&someObj.cvar) + 4));
(&someObj.cvar)
是一个指向char
的指针,所以*(&someObj.cvar)
是一个char
。 %f
printf
说明符需要 double
或 float
,传递 char
是无效的。注意:float
当在可变参数函数中作为省略号参数中的参数之一传递时,隐式转换为 double
,请参见 ex。 cppreference implicit conversions。您必须将 double
或 float
传递给 %f
,而不是 char
.
备注:
main(argc,argv)
const char** argv;
{
不要使用隐式 int
声明和旧的、已弃用的、过时的函数声明样式。使用普通样式:
int main(int argc, char **argv) {
printf("%u\n",&someObj.fvar);
是未定义的行为。 %u
需要 unsigned char
,而不是 float *
。您可以使用 %p
说明符打印 void*
指针:printf("%p\n", (void*)&someObj.fvar);
或将其转换为 unsinged int
:printf("%u\n", (unsigned int)(uintptr_t)(void*)&someObj.fvar);
C 在 stddef.h
中声明了一个宏 offsetof
来访问 "slack-bytes" 的数量(我更喜欢名字 "padding bytes" )。您可以:printf("%f", *(float*)((char*)&someObj + offsetof(struct someStruct, fvar)));
#include <stdio.h>
#include <stdlib.h>
struct someStruct {
int ivar;
char cvar;
float fvar;
};
main(argc,argv)
const char** argv;
{
struct someStruct someObj;
someObj.ivar = 1;
someObj.fvar = 2.3;
someObj.cvar = 'r';
printf("%u\n",&someObj.fvar);
printf("%u\n",(&someObj.cvar + 4));
printf("%f\n",*((&someObj.cvar) + 4));
printf("%f\n",someObj.fvar);
}
这是我编写的程序,它试图通过将 char 的地址加 4 来访问 fvar
的地址。
我知道松弛字节的概念。我试图访问那段记忆,瞧!它正确地打印了地址。
printf("%u\n",&someObj.fvar);
printf("%u\n",(&someObj.cvar + 4));
两者打印相同的地址。
然后我尝试通过以下方式访问fvar:
printf("%f\n",*((&someObj.cvar) + 4));
printf("%f\n",someObj.fvar);
和
0.000000
2.300000
是我的结果。
然后我意识到 char* 和 float* 的解释不同。
因此,我尝试了从 char* 到 float* 再到 float 以及从 char 到 float* 再到 float 的各种类型转换,并且在所有可能的点上都尝试过,例如 typecasting the returned address to float
,使用 4.0
而不是 4
(我意识到这不应该工作......但它没有),等等
不知何故,它只是不打印 2.300000
并继续打印 0.000000
我哪里漏掉了这个概念?
请注意,我有一个 64-bit MinGW
并添加了 slack-byte
(我知道有些人没有),我已经验证过:
printf("%u",sizeof(someObj.ivar));
printf("%u",sizeof(someObj.fvar));
printf("%u",sizeof(someObj.cvar));
printf("%u",sizeof(someObj));
分别产生 4
、4
、1
和 12 ....(sizeof(char) + 3)
。
P.S。我知道这是一个可怕的想法,但这是我通常学习概念的方式 XD
假设以下为真:
&someObj.cvar + 4 == &someObj.fvar
您可以将指针值转换为适当的类型:
printf("%f\n", *(float*)((&someObj.cvar) + 4));
(&someObj.cvar)
是一个指向char
的指针,所以*(&someObj.cvar)
是一个char
。 %f
printf
说明符需要 double
或 float
,传递 char
是无效的。注意:float
当在可变参数函数中作为省略号参数中的参数之一传递时,隐式转换为 double
,请参见 ex。 cppreference implicit conversions。您必须将 double
或 float
传递给 %f
,而不是 char
.
备注:
main(argc,argv)
const char** argv;
{
不要使用隐式 int
声明和旧的、已弃用的、过时的函数声明样式。使用普通样式:
int main(int argc, char **argv) {
printf("%u\n",&someObj.fvar);
是未定义的行为。%u
需要unsigned char
,而不是float *
。您可以使用%p
说明符打印void*
指针:printf("%p\n", (void*)&someObj.fvar);
或将其转换为unsinged int
:printf("%u\n", (unsigned int)(uintptr_t)(void*)&someObj.fvar);
C 在
stddef.h
中声明了一个宏offsetof
来访问 "slack-bytes" 的数量(我更喜欢名字 "padding bytes" )。您可以:printf("%f", *(float*)((char*)&someObj + offsetof(struct someStruct, fvar)));