Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么可以';我们在c或c+中使用直接寻址+;密码?_C++_C_Pointers - Fatal编程技术网

C++ 为什么可以';我们在c或c+中使用直接寻址+;密码?

C++ 为什么可以';我们在c或c+中使用直接寻址+;密码?,c++,c,pointers,C++,C,Pointers,当我连续编译和执行这段代码几次时,它将cc的地址报告为0x0012FF5C。但是,当我尝试使用foo中对printf的第二次调用打印该地址的字符串时,它打印垃圾,而不是打印“Hello”??为什么会这样??当我知道地址位于应用程序的地址空间内时(至少在我不重新启动电脑或启动其他需要大量空间并导致我的应用程序被调出的应用程序之前),如果我直接将地址作为参数paas,会有什么错 在两次执行之间,进程的内存位置可能已更改。你不能这样做,你正在试图阅读一个不被你的过程分配的地址。此外,我还有很多警告:

当我连续编译和执行这段代码几次时,它将cc的地址报告为0x0012FF5C。但是,当我尝试使用foo中对printf的第二次调用打印该地址的字符串时,它打印垃圾,而不是打印“Hello”??为什么会这样??当我知道地址位于应用程序的地址空间内时(至少在我不重新启动电脑或启动其他需要大量空间并导致我的应用程序被调出的应用程序之前),如果我直接将地址作为参数paas,会有什么错


在两次执行之间,进程的内存位置可能已更改。你不能这样做,你正在试图阅读一个不被你的过程分配的地址。此外,我还有很多警告:

test.c:在函数“foo”中:test.c:6:警告:格式“%x”要求类型为“unsigned int”,但参数2的类型为“char**”

test.c:7:警告:格式“%s”要求类型为“char*”,但参数2的类型为“int”

test.c:9:警告:格式“%x”要求类型为“unsigned int”,但参数2的类型为“char**”


< > >强>因为C或C++标准中没有任何东西来保证.<强>这些地址可以根据编译器/操作系统来预测,但不要指望它。
#include <stdio.h>

int main(void) {
    char s[] = "okay";
    printf("%p", (void*)s);
    return 0;
}  
#包括
内部主(空){
字符s[]=“好的”;
printf(“%p”,(void*)s);
返回0;
}  
我每次都会得到一个不同的地址(linux上的gcc)。不要使用“地址文字”;)

现代操作系统上的进程地址空间是随机的,以确保每次执行时的安全性:

我不认为您的(0x0012F5C)代表指针。尝试(字符*)(0x0012F5C)

除此之外,像其他告诉您的一样,这没有实际价值,因为不保证每次运行时字符串都位于该地址。这不是一个嵌入式程序集,您可以说将这个字符串放在这个位置,然后直接使用地址

当我知道地址

嗯,当你硬编码地址时,你对它一无所知,你只是在猜测它


一个事物的地址在同一个程序的执行之间发生变化的原因有很多。如果您正在更改代码(就像您在这里所做的那样),那么地址可能会更改的原因还有更多。

正如前面有人所说,您的代码在内存中的位置在执行期间可能会有所不同,变量的位置也会发生同样的情况。尝试运行此代码。它会打印您在内存中指向的变量的实际地址。您将看到,多次执行会产生完全不同的地址。永远记住这一点

 #include <stdio.h>

 void foo(char *cc[])
{
    printf("%x\n",cc);
    printf("%s\n",(0x0012FF5C)); //this line will fail, there is no guarantee to that
    cc++;
    printf("%x\n",cc);
}

int main()
{
    char *c[] = {"Hello","World"};
    printf("c array location: %p",c); //print location
    foo(c);
}
#包括
void foo(字符*cc[]
{
printf(“%x\n”,cc);
printf(“%s\n”,(0x0012F5C));//此行将失败,对此没有任何保证
cc++;
printf(“%x\n”,cc);
}
int main()
{
char*c[]={“你好”,“世界”};
printf(“c数组位置:%p”,c);//打印位置
傅(丙),;
}

好的,第一件事是,不要假设多次执行将返回相同的地址

现在。假设你很幸运,得到了相同的地址。请注意,
cc
是指针数组。您正在发送此数组的基址。您需要发送数组第一个元素的值

试试这个,如果你运气好的话

printf("%s\n",*((char**)(0x0012FF5C)));

如果你在没有和的机器上运行你的程序,你很可能会成功。这些技术/功能就是它不起作用的原因


每个进程都有自己的虚拟地址空间,处理器将其地址转换为硬件地址。

因为当第二个printf尝试将此字符数组*打印为字符串时,第一个printf会为您提供字符数组*的地址。

首先,
printf(“%x\n”,cc)
不打印
cc
的地址。它最多只能打印
cc
的值,但行为未定义,因为您为格式
%x
传递了错误的类型参数。它需要
unsigned int
,您提供了一个指针

实际上,最可能的行为是,它将打印
cc
值的最低有效部分(因此在32位机器上,它似乎可以工作,而在64位机器上,您看不到整个地址)。但它可能以不同的方式出错

其次,
cc
具有类型
char**
,因此
cc
的值不是指向字符串第一个字符的指针,而是指向
main
中数组
c
的第一个元素的指针。
%s
格式需要指向字符串第一个字符的指针。因此,即使
cc
的值实际上是
0x0012F5C
,使用
%s
格式将该值传递给
printf
也是错误的


您看到的“垃圾”是试图从指针数组打印指针数据,就好像它是属于字符串的字符数据一样。不是。我把你的例子简化了一点。如果知道字符串的地址,则可以从该地址读取

#include <stdio.h>

void foo(char cc[])
{
    int i;
    printf("%p\n",cc);
    printf("Type the address you would like to read:");
    scanf ("%x",&i);
    printf("Character value at your address: %c\n",*((char *)(i)));
}

int main()
{
    char c[] = "Hello";
    foo(c);
}

正如预期的那样,这将打印出
你好
的第四个字母

您应该强制作废*您的地址为standard.Hmmph-Wall-pedantic什么也没说,但你是对的,C99草稿对fprintf说“p参数应该是指向void的指针”。已编辑。@Kirilenko:是否存在从
T*
void*
的隐式转换any@David罗德里格斯:它不适用于这个例子,因为
printf
接受数量可变的参数,这些参数的类型在编译时不会被检查(因此,不会执行自动转换)。。。基址的值和第一个元素的值将是相同的。@user1232138检查我的编辑!基址和值不相同。取消对基地址和基ad处的值的引用
#include <stdio.h>

void foo(char cc[])
{
    int i;
    printf("%p\n",cc);
    printf("Type the address you would like to read:");
    scanf ("%x",&i);
    printf("Character value at your address: %c\n",*((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