A. char a[4]; strcpy(a,"abcd");“abcd”所占用的内存单元为5个字节,在vc6.0下编译竟然通过,为什么不溢出
确实会溢出,并且覆盖了a后面紧接的那个字节。但是溢出覆写的哪个字节属于哪个对象是不确定的,而且可能刚好本来就等于0,因此除了使a正常输出外,没有其它效果。
如果是栈中的自动变量,a后面紧接着的是a前面定义的对象。
编译器是没智能到能检查到溢出的,这是逻辑错误而不是语法错误,所以不会对此产生编译错误。
可以试试
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
unsigned long u = 0xFFFFFFFF;
char a[4];
strcpy(a, "abcd");
cout << a << endl;
cout << u << endl;
cin.get();
return 0;
}
可以看到u的值被改写了(在几乎所有的平台上应该是这样;至于改写成的值……和字节序有关,Windows等little endian的平台上是0xFFFFFF00,Mac等big endian的平台上是0x00FFFFFF)。
另外, 35254659 说到的 malloc 分配的空间比实际的要大,确实有这么回事。不过多的空间是不能使用的,因为这些空间是控制块,被用于存储连续内存本身的信息,供释放内存使用。如果覆盖了这些部分,那么 free 这块空间以后,程序可能会发生莫名其妙的错误,甚至直接崩溃。
====
[原创回答团]
B. 在C语言中如果已经知道了一个数据的内存地址,怎样直接从内存中读取出该数据
要读取内存数据的话,只能通过指针,你只能通过自己定义一个int的指针,让他指向一个内存地址,然后通过*指针的形式读出来。
你说的“我不想通过指针变量来直接输出该int数据的值,而是想直接读取内存的数据,看看和我定义的int数据值是否相同。”是没意义的,就好像你要确定我这个人是不是我这个人一样,如果你一定要写的话,可以写成这样。
#include<stdio.h>
int main()
{
int a=123,b=1234567;
int adda=&a,addb=&b;
int *m,*n;
m=adda;
n=addb;
//printf("*m=%d\t,*n=%d\n",*m,*n); //这里不用指针变量直接输出int数据
printf("m=%d\t,n=%d\n",a,b);
return 0;
}
这里的m和n已经和a,b没有任何逻辑联系了,他们只是表示两个内存段的数据而已。
再明确点可以写成
#include<stdio.h>
int main()
{
int a=123,b=1234567;
int adda=&a,addb=&b;//adda和addb仅仅表示两个内存地址
int contenta,contentb;
contenta=*adda;
contentb=*addb;//这两句的含义是两个内存地址里面的内容,他们和变量a,b没有逻辑关系
//printf("*m=%d\t,*n=%d\n",contenta,contentb); //这里不用指针变量直接输出int数据
printf("m=%d\t,n=%d\n",a,b);
return 0;
}
这里就是你说的比较a以及a所在的内存块(adda)里面内容是不是和a相等