先说一下强制转换,可以跳过。例子:
#include <stdio.h>
#include <stdint.h>
int main()
{
uint16_t a = 0xA5A1;
uint8_t b;
b = (uint8_t)a; // 16位强制转换为8位
printf("b=0x%X",b);
}
a是16位,b是8位,将a进行一次强制转换的结果给b。
我这里的输出结果是
b=0xA1
---------------------------------------正文----------------------------------------
include <stdio.h>
void funa(void)
{
printf("funa is called\n");
}
int main()
{
void (*p)(); // 定义一个函数指针
p=funa; // p中存放funa函数地址
(*p)(); // 运行funa
printf("0x%X",&funa); // 打印funa函数的地址
return 0;
}
我这里执行之后得到的结果是
funa is called
0x401530
第一行表示funa函数已经执行
第二行表示funa函数的地址为0x401530(在不同机器不同时间结果可能都不同)
以这里的结果为例,此时将上述代码的第11、12行改为
p=0x401530;
(*p)();
运行结果是相同的。
但是将11、12行合并为:
(*0x401530)();
编译器会报错。
也就是说,我们需要将 "0x401530"强制转换为函数地址
参照最开始的强制转换,这里的格式应该大体是这样的:
(*(_______)0x401530)();
接下来只需要考虑下划线里该填什么了
参照之前的
void (*p)(); // 定义一个函数指针
我们可以知道,下划线里应该写
void (*)()
那么结果就出来了,这里要想将11、12行合并为一句,只需要这么写:
(* (void (*)())0x401530)();
我这里修改之后的最终程序为:
#include<stdio.h>
void funa(void)
{
printf("funa is called\n");
}
int main()
{
(*(void(*)())0x401530)(); // 运行位于0x401530地址处的funa函数
printf("0x%X",&funa); // 打印funa函数的地址
return 0;
}
输出和之前是完全相同的。
--------------------------------------归题--------------------------------------
如果我们需要运行位于0地址处的函数(或者是从0地址处开始运行)
只需把上面的0x401530改成0即可
也就是
(*(void(*)())0)();
---------------------------------------拓展----------------------------------------
如果真的理解之后,可以配合typedef使用。
之前的例子可以这样写
#include<stdio.h>
typedef void (*funcptr)(); // 为函数指针类型定义别名funcptr
void funa(void)
{
printf("funa is called\n");
}
int main()
{
(*(funcptr)0x401530)(); // 运行位于0x401530地址处的funa函数
printf("0x%X",&funa); // 打印funa函数的地址
return 0;
}
参考资料: <C的陷阱与缺陷> 2.1章 Andrew Koenig著
分享到:
相关推荐
【void关键字和void指针的理解】 在C/C++编程中,`void`是一个非常重要的关键字,它具有特殊的含义。`void`表示“无类型”,它主要用于两种情况:函数的返回类型和函数的参数类型。 1. **void的含义**: - 当用于...
### void指针小结 #### 一、概述 在C/C++编程语言中,`void`关键字...正确理解和运用`void`及`void*`可以帮助开发者写出更加健壮和灵活的代码。同时,注意遵循相关规则和最佳实践,可以有效避免常见的错误和陷阱。
本实验通过按键控制LED灯的闪烁频率,进一步加深对按键和定时器的理解。 #### 2. 实验相关寄存器 - **T1CTL**:定时器1控制寄存器。 - **T1CCR0**:定时器1捕获/比较寄存器0。 - **T1IF**:定时器1中断标志位。 - *...
在C/C++编程语言中,`void`是一个非常关键的类型关键字,用于表示“无类型”...理解和正确使用`void`和`void *`是编写高效、可靠代码的关键。在实际编程中,应始终遵循类型匹配原则,避免因类型不匹配导致的潜在问题。
`memcpy`函数原型为`void* memcpy(void* dest, const void* src, size_t len);`,它用于复制`len`个字节从`src`到`dest`。`memset`函数原型为`void* memset(void* ptr, int value, size_t num);`,它用于将`num`个...
5. **避免混淆**:尽管 `void *` 非常灵活,但过度使用可能会导致代码难以理解。最好明确地指定指针的类型,除非确实需要 `void *` 的灵活性。 #### 结论 `void` 和 `void *` 指针是 C/C++ 编程中非常重要的概念。...
- **返回类型为void**:如果一个函数不返回任何值,那么应该声明其返回类型为`void`。这有助于避免编译器默认函数返回整型值的误解,同时增加了代码的可读性和规范性。 - **参数类型为void**:当函数不接受任何...
【void类型详解】 在C/C++编程语言中,`void`是一个非常特殊的关键词,它具有特定的含义和用途...理解并恰当使用`void`,有助于编写更清晰、更健壮的代码。在编程过程中,应遵循以上规则,确保代码的正确性和可读性。
void的含义void即“无类型”,void *则为“无类型指针”,可以指向任何数据类型。 void指针使用规范①void指针可以指向任意类型的数据,亦即可用任意数据类型的指针对void指针赋值。例如:int *pint;void *pvoid;...
事实上,只有深刻理解`void`指针的特性和使用场景,才能更好地掌握指针的高级用法。 #### 二、`void`关键字的基本含义 `void`的字面意思为“无类型”,这意指着它没有具体的类型关联。在C/C++中,`void`主要用来...
1. **加深理解文件系统的内部功能与实现:** 通过设计一个简单的多用户文件系统,帮助学习者更好地掌握文件系统的工作原理及其内部实现机制。 2. **结合多门课程知识:** 将数据结构、程序设计、计算机原理等课程知识...
- **void**:表明此函数没有返回值。在中断服务程序中通常不需要返回值,因为它们主要是用来响应外部事件或定时器溢出等触发条件,执行完相应的处理后立即退出。 - **timer0**:这是中断服务程序的名字,通常根据其...
本文档旨在对JFreeChart中的一些关键API进行详细解析,帮助开发者更好地理解和应用这些API来创建高质量的数据可视化图表。 #### 二、API详细解析 ##### 1. `Chart`类 **方法说明:** - **`void setAntiAlias...
在编程实践中,理解并正确使用`void`和`void *`可以提高代码的灵活性和通用性,同时确保类型安全。务必遵循相关的使用规则,避免因类型转换不当而导致的问题。特别是在处理跨平台或兼容性问题时,遵守标准非常重要,...
标题中的“error LNK2005 void __cdecl operator delete(void)”是一个常见的链接错误,它在C++编程中出现,通常涉及到多库编译时的符号重定义问题。这个错误表明在链接阶段发现了一个重复定义的`operator delete`...
在C/C++编程语言中,`void`关键字扮演着重要的角色,特别是在函数声明和指针操作中。`void`的基本含义是“无类型”,这意味着它不关联任何特定的数据类型。...正确理解和使用这些概念是编写高效、健壮代码的关键。
作为一名程序设计人员,对void的理解和使用正确性直接影响到程序的正确性和可读性。 1. void的含义 void的字面意思是“无类型”,void *则为“无类型指针”,void *可以指向任何类型的数据。void几乎只有“注释”...
3. **`void`指针**:`void*`是一种通用指针类型,它可以指向任何数据类型的对象,从而提供了一种灵活的数据操作机制。然而,`void*`不能直接用于算法操作(如递增、递减),除非将其转换为具体的类型指针。 #### `...