C语言 访问 C 中的特定内存位置
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15638105/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Accessing specific memory locations in C
提问by Deepu
In assembly language we have instructions like:
在汇编语言中,我们有如下指令:
movl ax, [1000]
This allows us to access specific memory locations.
这允许我们访问特定的内存位置。
But in C can we do something similar to this?
但是在 C 中我们可以做类似的事情吗?
I know inline assembly code using asm()will allow you to do this,
but I would like to know about some C specific technique to achieve this.
我知道使用内联汇编代码asm()可以让你做到这一点,但我想知道一些 C 特定的技术来实现这一点。
I tried the following code and got segmentation error:
我尝试了以下代码并出现分段错误:
int *ptr=0xFE1DB124;
*ptr;
This again was confusing as the memory location was identified by the code given below:
这再次令人困惑,因为内存位置由下面给出的代码标识:
int var;
printf("\nThe Address is %x",&var);
So the memory location is available, but I am still getting a segmentation fault.
所以内存位置可用,但我仍然遇到分段错误。
Why?
为什么?
采纳答案by Eric Postpischil
Common C compilers will allow you to set a pointer from an integer and to access memory with that, and they will give you the expected results. However, this is an extension beyond the C standard, so you should check your compiler documentation to ensure it supports it. This feature is not uncommonly used in kernel code that must access memory at specific addresses. It is generally not useful in user programs.
通用 C 编译器将允许您从整数设置指针并使用该指针访问内存,它们将为您提供预期的结果。但是,这是超出 C 标准的扩展,因此您应该检查编译器文档以确保它支持它。此功能在必须访问特定地址的内存的内核代码中并不少见。它通常在用户程序中没有用。
As comments have mentioned, one problem you may be having is that your operating system loads programs into a randomized location each time a program is loaded. Therefore, the address you discover on one run will not be the address used in another run. Also, changing the source and recompiling may yield different addresses.
正如评论所提到的,您可能遇到的一个问题是,每次加载程序时,您的操作系统都会将程序加载到随机位置。因此,您在一次运行中发现的地址不会是另一次运行中使用的地址。此外,更改源和重新编译可能会产生不同的地址。
To demonstrate that you can use a pointer to access an address specified numerically, you can retrieve the address and use it within a single program execution:
为了演示您可以使用指针访问数字指定的地址,您可以检索该地址并在单个程序执行中使用它:
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
int main(void)
{
// Create an int.
int x = 0;
// Find its address.
char buf[100];
sprintf(buf, "%" PRIuPTR, (uintptr_t) &x);
printf("The address of x is %s.\n", buf);
// Read the address.
uintptr_t u;
sscanf(buf, "%" SCNuPTR, &u);
// Convert the integer value to an address.
int *p = (int *) u;
// Modify the int through the new pointer.
*p = 123;
// Display the int.
printf("x = %d\n", x);
return 0;
}
Obviously, this is not useful in a normal program; it is just a demonstration. You would use this sort of behavior only when you have a special need to access certain addresses.
显然,这在普通程序中是没有用的;这只是一个示范。仅当您有特殊需要访问某些地址时才会使用这种行为。
回答by SomeOne
For accessing Specific memory from user space, we have to map the memory Address to Programs Virtual Address using mmap(), the below C code shows the implementation:
为了从用户空间访问特定内存,我们必须使用mmap()将内存地址映射到程序虚拟地址,下面的 C 代码显示了实现:
Take a file "test_file" containing "ABCDEFGHIJ".
取一个包含“ABCDEFGHIJ”的文件“ test_file”。
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
int main(void)
{
char *map_base_addr; // Maping Base address for file
int fd; // File descriptor for open file
int size = 10;
fd= open("test_file", O_RDWR); //open the file for reading and writing
map_base_addr= mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);// Maping file into memory
char *ch= map_base_addr;
int i;
/*Printing first 10 char*/
for(i=0; i<size; i++)
fputc(*(ch+i),stdout);
printf("\n");
*(ch+1) = 'b';
*(ch+4) = 'z';
*(ch+7) = 'x';
/*Printing char after modification*/
for(i=0; i<size; i++)
fputc(*(ch+i),stdout);
printf("\n");
/* Finally unmap the file. This will flush out any changes. */
munmap(map_base_addr, size);
exit(0);
}
The output will be:
输出将是:
ABCDEFGHIJ
AbCDzFGxIJ
回答by Klas Lindb?ck
It works for me:
这个对我有用:
#include <stdio.h>
int main(int argc, char**argv) {
int var = 7456;
printf("Adress of var = %x, var=%d\n", &var, var);
int *ptr = (int*)0x22cd28;
printf(" ptr points to %x\n", ptr);
*ptr = 123;
printf("New value of var=%d\n", var);
return 0;
}
Program output:
程序输出:
Adress of var = 22cd28, var=7456
ptr points to 22cd28
New value of var=123
Note:
笔记:
The address is usually not the same on every execution. When I tried my example I had to run it three times before I got the address to match.
char*can point to any adress (because sizeof (char) = 1). Pointers to larger objects must often be aligned on even adresses (usually one divisible by 4).
每次执行时地址通常都不相同。当我尝试我的例子时,我必须运行它三遍才能得到匹配的地址。
char*可以指向任何地址(因为 sizeof (char) = 1)。指向较大对象的指针通常必须在偶数地址上对齐(通常是可被 4 整除的)。
回答by LtWorf
Your question doesn't really make much sense if you are running on linux/windows/mac/whatever
如果您在 linux/windows/mac/whatever 上运行,那么您的问题并没有多大意义
http://en.wikipedia.org/wiki/Virtual_memory
http://en.wikipedia.org/wiki/Virtual_memory
You can do that only if you are programming a device without virtual memory, or if you are programming the operating system itself.
只有在对没有虚拟内存的设备进行编程,或者对操作系统本身进行编程时,才能这样做。
Otherwise the addresses you see are not the "real" addresses on the RAM, the operating system translates them to real addresses and if there is not a map to translate your virtual address to a real one, then you can get a segmentation fault. Keep in mind that there are other reasons that can cause a segmentation fault.
否则,您看到的地址不是 RAM 上的“真实”地址,操作系统会将它们转换为真实地址,如果没有映射将您的虚拟地址转换为真实地址,那么您可能会遇到分段错误。请记住,还有其他可能导致分段错误的原因。

