我想知道我们是否可以仅使用C语言中该位置的裸地址在特定位置打印数据。
例如,以下是我使用的代码:
#include<stdio.h>
int main(int argc, char** argv) {
int num = 10;
int *ptr;
ptr = #
//To output the address of the "num" variable
printf("Address: %p\n", ptr);
//Address is 0x7fff47808f50...
//Using that address to print the data at variable "num"
printf("Data: %d\n", *(0x7fff47808f50));
return 0;
}
但它显示错误。也许我使用了错误的语法,或者这可能不是这样做的。不管怎样,请告诉我正确的方法。
答案 0 :(得分:2)
你可以(以为不应该)将整数强制转换为如下指针:(void *) 0x7fff47808f50
。
转换具有实现定义和未定义的方面,但这意味着您的里程会有所不同。这个值显然会从编译器变为编译器,甚至可能是针对不同的编译,并且字节顺序可能与我们常规编写数字的方式不同,这意味着您可能需要修改一下才能使其正常工作。
这在实践中是可证明的,当实现定义的行为允许我们重现该行为时,以下内容将是合规的:
unsigned long long ptr_as_integer = (unsigned long long) "hello world";
printf("%s", (void *) ptr_as_integer);
int value = 42;
unsigned long long value_ptr_as_integer = (unsigned long long) &value;
printf("%d", * (int *) value_ptr_as_integer);
还有uintptr_t
类型,专为此设计,但可选,因此无法保证存在...
好奇是好的;这就是我们学得最好的方法......但请不要在实践中使用它!你多久被教导不使用魔法数字?
答案 1 :(得分:1)
您可以使用char *
为另一种类型的指针设置别名来读取单个字节:
int i;
char *p = (char *)ptr;
for (i=0; i<sizeof(*ptr); i++) {
printf("p[%d]=%02hhx", i, p[i]);
}
答案 2 :(得分:1)
修改您的代码
#include<stdio.h>
int main(int argc, char** argv) {
int num = 10;
int *ptr;
ptr = #
//To output the address of the "num" variable
printf("Address: %p\n", ptr);
//Address is 0x7fff47808f50...
//Using that address to print the data at variable "num"
printf("Data: %d\n", *ptr);
return 0;
}
你问的答案是肯定的。
BUT:
您必须100%确定要使用的地址。例如,在任何类型的固件中,您总是将手册中定义的寄存器地址作为常规数字。我们像这样使用它们
#define MY_REG_ADDR 0x12345ABC
int a = *((int*)(MY_REG_ADDR))
现代操作系统确实解决了随机化问题,因此每次运行应用程序时都会更改可执行文件的虚拟地址sapce,因此您不能只使用硬编码地址。
这是我运行应用程序4次后的输出(修改后的代码)
地址:0x7ffc279af5ac
数据:10
地址:0x7ffc2d78021c
数据:10
地址:0x7fffb36ae32c
数据:10
地址:0x7ffca2c2a9ec
数据:10