显示不同值的C变量

显示不同值的C变量,c,C,我的一个程序中出现了一些意想不到的行为。经过进一步的分析,我在下面缩短的代码中发现了一些奇怪的结果 #include <stdio.h> int main() { int k = 0; int rstr[200]; printf("value of k= %d\n",k); printf("adress of k = %x\n",&k); printf("adress of rstr[0] = %x\n",&rstr

我的一个程序中出现了一些意想不到的行为。经过进一步的分析,我在下面缩短的代码中发现了一些奇怪的结果

#include <stdio.h>
int main() {
     int k = 0;
     int rstr[200];
     printf("value of  k= %d\n",k);
     printf("adress of k = %x\n",&k);
     printf("adress of rstr[0] = %x\n",&rstr[0]);
     printf("adress of rstr[199] = %x\n",&rstr[199]);


     rstr[200] = " ";
     printf("value of  k= %d\n",k);
     printf("adress of k = %x\n",&k);
     printf("adress of rstr[200] = %x\n",&rstr[200]);
     return 0;
   }
#包括
int main(){
int k=0;
int rstr[200];
printf(“k的值=%d\n”,k);
printf(“k的地址=%x\n”,&k);
printf(“rstr[0]的地址=%x\n”、&rstr[0]);
printf(“rstr[199]的地址=%x\n”,&rstr[199]);
rstr[200]=“”;
printf(“k的值=%d\n”,k);
printf(“k的地址=%x\n”,&k);
printf(“rstr[200]的地址=%x\n”、&rstr[200]);
返回0;
}

rstr[200]大小过大,因此它将包含垃圾值,但是,它是如何传递给变量k的。请回答。

&rstr[200]
已超出
rstr
数组。因此,访问这个地址在理论上是无效的(未定义的行为),而打印它是可以的(只要您使用
%p
作为指针的格式)

在您的例子中,编译器似乎先将
rstr
放在自动变量分配区域中,然后将
k
放在自动变量分配区域中,这说明两个地址匹配(在这种情况下
rstr[200]
不包含垃圾值,而是
k

当然,不要依赖于此……这只是给出一个解释(有些黑客使用这种技术,称为缓冲区溢出,使程序崩溃(DOS攻击),甚至通过更改返回地址以指向注入代码来控制程序)

(还请注意,
rstr[200]=”;
也未定义,无论
rstr
的大小是什么:在
int
数组中的文本上分配一个指针并不太好……)

rstr[200]
大小过大,因此它将包含垃圾值

不,访问
rstr[200]
并不意味着您将获得垃圾值。这是不允许兼容程序执行的操作。越界数组访问会导致您的程序具有未定义的行为。您可以观察任何情况


在您的特定情况下,编译器将
k
紧跟在数组
rstr
之后放入内存中。因此修改
rstr[200]
会导致
k

的混乱编译时我注意到以下错误:

 prog.c: In function 'main':
prog.c:11:16: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
      rstr[200] = " ";
                ^
prog.c:11:10: warning: array subscript is above array bounds [-Warray-bounds]
      rstr[200] = " ";
      ~~~~^~~~~
  • 越界访问是一种未定义的行为,可能会产生意外的输出
  • 根据C11-ISO标准: 如果转换规范无效,则行为未定义

  • 因此,请始终使用
    %p
    打印指针地址,并将其强制转换为
    void*
    到参数

    例如:

    printf("adress of k = %p\n",(void*)&k);
    
    关于未定义的行为:

    使用不可移植或错误的程序结构或错误的数据时的行为,本国际标准对此不作要求


    奖励:始终使用最新的编译器,并启用标志-Wall-O2-pedantic errors以查看所有警告。

    未定义。行为。您的问题最好以文本形式输出,而不是以图像形式输出。使用
    %p
    打印指针值:
    printf(“k的地址=%p\n”,(void*)&k)这几乎是唯一需要显式地将ponter值转换为
    void*
    的地方。