2017-09-16 114 views
-1

我在我的一个程序中出现了一些意想不到的行为。经过进一步分析,我在下面缩短的代码中发现了一些奇怪的结果。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[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; 
    } 

RSTR [200]是出的大小,以便它将包含垃圾值,但是,它是如何传递到变量k。请回答。 Output

+5

未定义。行为。 – StoryTeller

+1

你的问题会更好,输出为文字,而不是图像。 –

+0

使用'%p'打印指针值:'printf(“k =%p \ n”的地址,(void *)&k);'这是你唯一需要将ponter值明确地转换为void * '。 –

回答

3

rstr[200]超出尺寸的所以它会包含垃圾值

不,访问rstr[200]并不意味着你会得到垃圾值。这不是合规计划允许做的事情。超出范围的数组访问会导致您的程序出现未定义的行为。你可以观察任何东西

在您的特定情况下,编译器在存储器阵列rstr后立即发出k。因此修改rstr[200]最终与k混淆。

1

&rstr[200]不在rstr数组中。所以访问这个地址是theorically无效(未定义行为),在打印过程中它是好的(只要你使用%p的格式,指针

在你的情况,似乎编译器已经把rstr第一则k在自动变量分配区域,这说明两个地址匹配(在这种情况下,rstr[200]包含垃圾回收价值,但当然的k

值,不依赖于...这只是给出一个解释(好吧,一些黑客使用这种技术,称为buffer ov erflow,使程序崩溃(DOS攻击)或甚至通过更改返回地址指向注入的代码来控制程序)。

(也注意到,rstr[200] = " ";也是不确定的任何的rstr大小:在int数组分配上面值的指针不工作也很好......)

0

这些都是编译时,我注意到以下错误:

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] = " "; 
     ~~~~^~~~~ 
  1. 访问越界的是未定义的行为,它可能会产生意想不到的输出。
  2. 根据C11-ISO标准:

    如果转换规范无效,则行为是不确定的。

因此,一定要使用%p打印采用铸造一个指针,指向void*的说法。

对于前:

printf("adress of k = %p\n",(void*)&k); 

关于未定义行为:

行为,在使用非便携式或错误的程序结构的或错误的数据,这本国际标准并没有规定要求

BONUS:总是使用带有标志的最新编译器-Wall -O2 -pedantic-errors启用查看所有警告。