2017-08-15 81 views
2

我想知道我们是否可以通过使用C语言中该位置的裸地址在特定位置打印数据。我们可以通过在C中使用裸地址来打印数据吗?

用于例如,下面是我使用的代码:

#include<stdio.h> 

int main(int argc, char** argv) { 

    int num = 10; 
    int *ptr; 
    ptr = &num; 

    //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; 
} 

但它显示错误。也许我使用了错误的语法,或者这不是做这件事的方法。总之,请告诉我正确的方法来做到这一点。

+1

是什么让你觉得总是会有在您的地址'0x7fff47808f50'的东西吗? – litelite

+2

地址发生了变化,它并不总是这样......你必须将它设置为一个整数指针,否则如何解码类型? –

+0

请注意,这是变量“num”的地址,我将它赋值为10. –

回答

1

可以使用char *别名另一种类型的指针读取单个字节:

int i; 
char *p = (char *)ptr; 
for (i=0; i<sizeof(*ptr); i++) { 
    printf("p[%d]=%02hhx", i, p[i]); 
} 
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

问题的含义详细内容:尽管当然合理,'(无符号long long)“hello world”;'没有被指定为“工作”或者是'unsigned long long'缺乏足够的宽度 - 甚至是“uintmax_t”。这种情况可能发生在不存在'(u)intptr_t'的平台上。国际海事组织,当使用指针/从整数,使用'uintptr_t'更好。如果缺少'uintptr_t',代码的替代方法可能也是可疑的,最好不要编译。 – chux

+0

@chux感谢批评,但我认为我的回答已经表达了您的担忧。你有什么有用的补充,但尚未被覆盖? – Sebivor

+0

字节顺序对文字无关紧要。这可能是因为在一个小端机器上,该值存储为{0x50,0x8F,0x80,...}。事实上,这是一个发生这种情况的平台。 http://ideone.com/7OU7GY。尽管我已经使用'uintptr_t'来最大程度的保证我使用了一个兼容指针的类型(如果这样的东西是可用的......)。 – Persixty

1

修改代码

#include<stdio.h> 

int main(int argc, char** argv) { 
    int num = 10; 
    int *ptr; 
    ptr = &num; 

    //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; 
} 

想问你的是YES的答案。

但是:

  1. 你必须100%确定使用什么地址。例如,在任何类型的固件中,您都将手册中定义的寄存器地址定义为常规数字。我们使用它们像这样

    #define MY_REG_ADDR 0x12345ABC 
    int a = *((int*)(MY_REG_ADDR)) 
    
  2. 现代的操作系统做地址随机这样可执行文件的虚拟地址sapce改变每次运行你的应用程序,所以你不能只使用硬编码地址的时间。

这里是后我跑的应用的输出的4倍(修改后的代码)

地址:0x7ffc279af5ac
数据:10
地址:0x7ffc2d78021c
数据:10
地址:0x7fffb36ae32c
Data:10
Address:0x7ffca2c2a9ec
Data:10

  • 你改变你的代码的内存布局可能会改变每齿所以variabl的地址也可能改变
  • +0

    的确,这就是我几分钟前得到的结果。每次编译后,地址都在不断变化。 –

    +2

    @YatendraRathore不仅在每次编译之后,而且在现代操作系统中使用[ASLR](https://en.wikipedia.org/wiki/Address_space_layout_randomization),每次运行后地址都会改变 –

    相关问题