显示不同值的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*
的地方。