为什么我们不能在 C 或 C++ 代码中使用直接寻址?
Why can't we use direct addressing in c or c++ code?
当我连续编译并执行这段代码几次时,它将cc的地址报告为0x0012FF5C。但是当我尝试使用在 foo 中第二次调用 printf 来打印该地址的字符串时,它会打印垃圾而不是打印出"Hello"??为什么会这样??如果我知道地址位于应用程序的地址空间内时,我直接将地址作为参数(至少在我不重新启动PC或启动其他需要大量空间并导致我的应用程序被分页的应用程序之前)有什么问题??
void foo(char *cc[])
{
printf("%xn",cc);
printf("%sn",(char *)(0x0012FF5C));
}
int main()
{
char *c[] = {"Hello","World"};
foo(c);
}
因为 C 或 C++ 标准中没有任何内容可以保证这一点。 这些地址可能是可预测的,具体取决于您的编译器/操作系统,但不要指望它。
#include <stdio.h>
int main(void) {
char s[] = "okay";
printf("%p", (void*)s);
return 0;
}
我每次都会得到一个不同的地址(linux上的gcc)。 不要使用"地址文字";)
现代操作系统上的进程地址空间是随机的,以确保每次执行的安全性:
http://en.wikipedia.org/wiki/Address_space_layout_randomization
因为当第二个 printf 尝试将此 char* 数组打印为字符串时,第一个 printf 会为您提供 char* 数组的地址。
好的,第一件事是,永远不要假设多个执行将返回相同的地址
现在,假设您很幸运并获得了相同的地址。请注意,cc
是一个指针数组。您正在发送此数组的基址。您需要发送数组第一个元素的值
试试这个,如果你幸运的话,它有效,
printf("%sn",*((char**)(0x0012FF5C)));
如果您在没有虚拟内存和内存保护的计算机上运行程序,则很可能会成功。这些技术/功能是它不起作用的原因。
每个进程都有自己的虚拟地址空间,其地址由处理器的内存管理单元转换为硬件地址。
我不认为你的(0x0012FF5C)代表poiter。尝试 (字符*)(0x0012FF5C)。
除此之外,就像其他人告诉你的那样,这没有实际价值,因为不能保证每次运行都会在该地址找到字符串。这不是一些嵌入式程序集,您说将此字符串放在此位置,然后直接使用该地址。
进程的内存位置可能在两次执行之间发生了更改。你不能那样做,你试图阅读一个没有被你的过程分配的地址。此外,我有很多警告:
test.c:在函数 'foo' 中: test.c:6: 警告:格式 '%x' 需要类型'unsigned int',但参数 2 的类型为 'char **'
test.c:7:警告:格式"%s"需要类型"char *",但参数 2 的类型为"int"
test.c:9:警告:格式"%x"需要类型"无符号整数",但参数 2 的类型为"char **"
好吧,当你对地址当我知道地址
进行硬编码时,你对地址一无所知,你是在猜测它。
事物的地址在执行同一程序之间可能会发生变化的原因有很多。如果您正在更改代码,地址可能会更改的原因还有更多(就像您在此处所做的那样)。
正如之前有人所说,您在内存中的代码位置可能会因执行而异,变量的位置也会发生同样的情况。尝试运行此代码。它打印您在内存中指向的变量的实际地址。 您将看到多个执行会产生完全不同的地址。永远记住这一点!
#include <stdio.h>
void foo(char *cc[])
{
printf("%xn",cc);
printf("%sn",(0x0012FF5C)); //this line will fail, there is no guarantee to that
cc++;
printf("%xn",cc);
}
int main()
{
char *c[] = {"Hello","World"};
printf("c array location: %p",c); //print location
foo(c);
}
首先,printf("%xn",cc);
不打印cc
的地址。充其量它打印 cc
的值,但行为是未定义的,因为您为格式传递了错误的类型参数 %x
。它期望unsigned int
,您已经提供了一个指针。
在实践中最可能的行为是它将打印cc
值中最不重要的部分(因此在 32 位计算机上它看起来可以工作,而在 64 位计算机上,您不会看到整个地址)。但它可能会以不同的方式出错。
第二件事,cc
具有类型 char**
,因此 cc
的值不是指向字符串第一个字符的指针,而是指向数组的第一个元素的指针,c
来自main
。%s
格式需要一个指向字符串第一个字符的指针。因此,即使cc
的值确实是0x0012FF5C
,将该值传递给具有%s
格式的printf
也是错误的。
您看到的"垃圾"是尝试从该指针数组打印指针数据,就好像它是属于字符串的字符数据一样。其实不然。
简化了你的例子。如果您知道字符串的地址,则可以从该地址读取。
#include <stdio.h>
void foo(char cc[])
{
int i;
printf("%pn",cc);
printf("Type the address you would like to read:");
scanf ("%x",&i);
printf("Character value at your address: %cn",*((char *)(i)));
}
int main()
{
char c[] = "Hello";
foo(c);
}
这将允许您从命令行指定的地址读取。它将首先打印出字符数组的基址,以便您知道在哪里查找字符串。
例:
$ ./a.out
0xbfcaaf3a
Type the address you would like to read:bfcaaf3d
Character value at your address: l
不出所料,这打印了Hello
的第四个字母。
- 从结构寻址时,MMAP变量的行为很奇怪
- 字节真的是最小可寻址单元吗
- 具有两个间接寻址运算符 (C++) 的函数参数的用途
- imread() 仍然返回空垫子,尽管在 openCV 4.0.0 中寻址正确
- 在具有开放寻址的哈希表中插入节点 [优化逻辑]
- 如何像在 C++ 中处理数组一样对 .txt 文件中的字符进行寻址?
- 如何使用指针直接从托管代码中的非托管代码中读取矢量数据
- C++11右值引用寻址
- 对堆栈增长和寻址的困惑
- 生成可以在PHP中加密的密钥,该密钥可以直接放置在C 代码中以进行解密
- C++ std::find() 寻址返回向量的类函数时的意外行为
- 间接寻址运算符如何返回带有运算符重载的指针地址
- Adafruit NeoPixel库在寻址超过7个LED灯条时不起作用
- 在模板 SFINAE 约束中使用间接寻址级别会导致硬错误
- 错误:使用索引寻址和 Clang 的指令的操作数无效
- 是否可以寻址另一个网络中的服务器/客户端套接字?(C++)
- C++中的字节寻址算法
- 指针声明和间接寻址之间的区别
- C/C++中的6502仿真器:如何将寻址模式代码与实际指令代码分离
- 为什么我们不能在 C 或 C++ 代码中使用直接寻址?