转换为 char 数组的函数地址
function address cast to char array
为了我的教育目的,我想知道是否有 memcpy() 的替代方法来将函数地址转换为字符数组的以下代码?
#include <stdio.h>
#include <string.h>
typedef void (*_vfp)(void);
#define FPSZ sizeof(_vfp)
union rcast {
_vfp fp;
char fp_c[FPSZ];
} rc;
void a(void){
printf("a()\n");
}
int main(int argc, char **argv)
{
int i=0;
memset(&rc,0,FPSZ);
rc.fp=a;
for (i=0;i<FPSZ;++i)
printf("%hhx ",rc.fp_c[FPSZ-i-1]);
puts("");
printf("%p\n",a);
return 0;
}
谢谢。
对代码进行最少的修改:
#include <stdio.h>
#include <string.h>
typedef void (*_vfp)(void);
#define FPSZ sizeof(_vfp)
void a(void){
printf("a()\n");
}
int main(int argc, char **argv)
{
int i=0;
_vfp fp = a;
char fp_c[FPSZ];
memcpy(fp_c, &fp, FPSZ);
for (i=0;i<FPSZ;++i)
printf("%hhx ",fp_c[FPSZ-i-1]);
puts("");
printf("%p\n",a);
return 0;
}
编辑:作为对评论的回应,这里有一个没有代理和 memcpy 的版本
#include <stdio.h>
#include <stdint.h>
#include <limits.h>
#include <string.h>
typedef void (*_vfp)(void);
#define FPSZ sizeof(_vfp)
void a(void){
printf("a()\n");
}
int main(int argc, char **argv)
{
int i=0;
char fp_c[FPSZ];
for (i=0;i<FPSZ;++i)
fp_c[i] = (char) (((uintptr_t) &a) >> CHAR_BIT * i);
for (i=0;i<FPSZ;++i)
printf("%hhx ",fp_c[FPSZ-i-1]);
puts("");
printf("%p\n",a);
return 0;
}
For my educational purposes I was wondering if there is an alternative way with memcpy() to the following code for the function address casting to an array of chars?
请注意:虽然数组和指针密切相关,但它们是截然不同的东西。在许多其他差异中,您可以在强制转换运算符中使用指针类型,并将指针用作强制转换操作数,但您不能在这些上下文中使用数组类型或数组。
你似乎在说你想要的是一个包含函数指针值字节的字符数组(而不是指针指向的字节)。您可以通过多种方式获得它或类似的东西。最简单的方法是创建指向指针值的 char *
。同样,这 不是 数组,但它可以以许多与数组相同的方式使用:
typedef void (*_vfp)(void);
int main(int argc, char **argv)
{
int i;
_vfp fp = a;
char *cp = &fp;
for (i = 0; i < sizeof(fp); ++i) {
printf("%hhx ", cp[i]);
}
printf("\n%p\n", (void *) a);
return 0;
}
但是请注意,上面的代码表现出未定义的行为。 %p
字段描述符告诉 printf()
相应的参数是一个 object 指针。 C 区分了对象指针和函数指针,并且没有定义任何在这两种类型族的值之间进行转换的行为。我包括一个明确表达这种转换的转换(这可能使编译器注意到并抱怨);您的代码导致隐式执行此类转换。
如果你想要一个单独的数组对象包含指针值的字节(而不是指向函数的值),那么你可以用类似的方式得到它:
int main(int argc, char **argv)
{
_vfp fp = a;
char array[sizeof(fp)];
memcpy(array, &fp, sizeof(array));
/* ... */
}
那个使用 memcpy()
,完全按照你的要求。
不管怎么说,都没有工会的必要。事实上,尽管您的基于联合的方法可能碰巧适用于您的 C 实现,但从与最近写入的不同联合成员读取正式展示未定义的行为。
你正在做的是正式的未定义行为。 C 语言说联合可以包含任何不同的变量,但您只能访问在联合中设置的变量:联合的大小足以包含其最大的成员。在的值
大多数成员可以随时存储在联合对象中。(参考:C 语言规范草案 - 6.7.2.1 结构和联合说明符 - 16)
因此,它与通过 void 进行指针转换既不是最好也不是更差:
intptr_t ip = (intptr_t) &a;
char *fp_c = (void *) &intptr_t;
或 memcpy
:
char fp_c[FPSZ];
intptr_t ip = (intptr_t) &a;
memcpy(fp_c, &ip, sizeof(intptr_t));
所有人都会给你相同的结果:
for (i=0; i<FPSZ; i++) {
printf("%hhx ",fp_c[FPSZ-i-1]);
}
fputs("\n");
为了我的教育目的,我想知道是否有 memcpy() 的替代方法来将函数地址转换为字符数组的以下代码?
#include <stdio.h>
#include <string.h>
typedef void (*_vfp)(void);
#define FPSZ sizeof(_vfp)
union rcast {
_vfp fp;
char fp_c[FPSZ];
} rc;
void a(void){
printf("a()\n");
}
int main(int argc, char **argv)
{
int i=0;
memset(&rc,0,FPSZ);
rc.fp=a;
for (i=0;i<FPSZ;++i)
printf("%hhx ",rc.fp_c[FPSZ-i-1]);
puts("");
printf("%p\n",a);
return 0;
}
谢谢。
对代码进行最少的修改:
#include <stdio.h>
#include <string.h>
typedef void (*_vfp)(void);
#define FPSZ sizeof(_vfp)
void a(void){
printf("a()\n");
}
int main(int argc, char **argv)
{
int i=0;
_vfp fp = a;
char fp_c[FPSZ];
memcpy(fp_c, &fp, FPSZ);
for (i=0;i<FPSZ;++i)
printf("%hhx ",fp_c[FPSZ-i-1]);
puts("");
printf("%p\n",a);
return 0;
}
编辑:作为对评论的回应,这里有一个没有代理和 memcpy 的版本
#include <stdio.h>
#include <stdint.h>
#include <limits.h>
#include <string.h>
typedef void (*_vfp)(void);
#define FPSZ sizeof(_vfp)
void a(void){
printf("a()\n");
}
int main(int argc, char **argv)
{
int i=0;
char fp_c[FPSZ];
for (i=0;i<FPSZ;++i)
fp_c[i] = (char) (((uintptr_t) &a) >> CHAR_BIT * i);
for (i=0;i<FPSZ;++i)
printf("%hhx ",fp_c[FPSZ-i-1]);
puts("");
printf("%p\n",a);
return 0;
}
For my educational purposes I was wondering if there is an alternative way with memcpy() to the following code for the function address casting to an array of chars?
请注意:虽然数组和指针密切相关,但它们是截然不同的东西。在许多其他差异中,您可以在强制转换运算符中使用指针类型,并将指针用作强制转换操作数,但您不能在这些上下文中使用数组类型或数组。
你似乎在说你想要的是一个包含函数指针值字节的字符数组(而不是指针指向的字节)。您可以通过多种方式获得它或类似的东西。最简单的方法是创建指向指针值的 char *
。同样,这 不是 数组,但它可以以许多与数组相同的方式使用:
typedef void (*_vfp)(void);
int main(int argc, char **argv)
{
int i;
_vfp fp = a;
char *cp = &fp;
for (i = 0; i < sizeof(fp); ++i) {
printf("%hhx ", cp[i]);
}
printf("\n%p\n", (void *) a);
return 0;
}
但是请注意,上面的代码表现出未定义的行为。 %p
字段描述符告诉 printf()
相应的参数是一个 object 指针。 C 区分了对象指针和函数指针,并且没有定义任何在这两种类型族的值之间进行转换的行为。我包括一个明确表达这种转换的转换(这可能使编译器注意到并抱怨);您的代码导致隐式执行此类转换。
如果你想要一个单独的数组对象包含指针值的字节(而不是指向函数的值),那么你可以用类似的方式得到它:
int main(int argc, char **argv)
{
_vfp fp = a;
char array[sizeof(fp)];
memcpy(array, &fp, sizeof(array));
/* ... */
}
那个使用 memcpy()
,完全按照你的要求。
不管怎么说,都没有工会的必要。事实上,尽管您的基于联合的方法可能碰巧适用于您的 C 实现,但从与最近写入的不同联合成员读取正式展示未定义的行为。
你正在做的是正式的未定义行为。 C 语言说联合可以包含任何不同的变量,但您只能访问在联合中设置的变量:联合的大小足以包含其最大的成员。在的值 大多数成员可以随时存储在联合对象中。(参考:C 语言规范草案 - 6.7.2.1 结构和联合说明符 - 16)
因此,它与通过 void 进行指针转换既不是最好也不是更差:
intptr_t ip = (intptr_t) &a;
char *fp_c = (void *) &intptr_t;
或 memcpy
:
char fp_c[FPSZ];
intptr_t ip = (intptr_t) &a;
memcpy(fp_c, &ip, sizeof(intptr_t));
所有人都会给你相同的结果:
for (i=0; i<FPSZ; i++) {
printf("%hhx ",fp_c[FPSZ-i-1]);
}
fputs("\n");