我的一个程序中出现了一些意想不到的行为。经过进一步分析后,我在下面的缩短代码中发现了一些奇怪的结果。
#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
答案 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] = " ";
~~~~^~~~~
如果转换规范无效,则行为未定义。
因此,请始终使用%p
打印指针地址,并将void*
强制转换为参数。
例如:
printf("adress of k = %p\n",(void*)&k);
关于未定义的行为:
使用不可移植或错误的程序结构或错误数据的行为,本国际标准没有规定
奖励:始终使用带有标志-Wall -O2 -pedantic-errors的最新编译器来查看所有警告。