C变量显示不同的不同值

时间:2017-09-16 14:25:49

标签: 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

3 个答案:

答案 0 :(得分:3)

  

class NetworkCom { private: SOCKADDR_IN ClientAddress; int ClientAddressSize; SOCKET SenderSocket; public: NetworkCom(SOCKET& sock) { ClientAddressSize = sizeof(ClientAddress); getpeername(sock,(SOCKADDR*)&ClientAddress,&ClientAddressSize); sock = socket(AF_INET,SOCK_STREAM,0); SenderSocket = socket(AF_INET,SOCK_STREAM,0); } int SendData(char message[]) { int val; val = send(sock,message,sizeof(message),0); // if val <= 0 then error return val; } string RecieveData() { string message; char msg[100]; connect(SenderSocket,(SOCKADDR*)&ClientAddress,&ClientAddressSize); recv(SenderSocket,msg,100,0); message = msg; return message; } ~NetworkCom() { cout<<"Closing Connection.."; closesocket(SenderSocket); closesocket(sock); } }; 超出了大小,因此它将包含垃圾值

不,访问rstr[200]并不意味着您将获得垃圾值。它不是一个合规程序可以做的事情。超出范围的数组访问会导致程序具有未定义的行为。你可以观察任何事情

在您的特定情况下,编译器会在数组rstr[200]之后立即将k 放在内存中。因此,修改rstr最终会弄乱rstr[200]

答案 1 :(得分:1)

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

在你的情况下,似乎编译器先将rstr放在自动变量分配区域中,然后k,这解释了两个地址匹配(在这种情况下rstr[200]做< em> not 包含垃圾值,但值k

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

(还要注意rstr[200] = " ";也是未定义的,无论rstr的大小是多少:在int数组中的文字上指定指针不能很好地工作......)

答案 2 :(得分: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标准:
      

    如果转换规范无效,则行为未定义。

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

    例如:

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

    关于未定义的行为:

      使用不可移植或错误的程序结构或错误数据的行为,本国际标准没有规定

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