C编程: 为什么指针一定要malloc分配空间?

type * p时,系统不是给p分配了type大小的空间吗?为什么都说这个空间不能用呢?
我自己测试的结果,double * p, 发现sizeof(*p)确实是8字节大小,而且也可以*p=5这样赋值,这样用不对吗?

你需要分清“指针所占用的内存空间”和“指针指向的内存空间”之间的区别。指针变量需要存储它所指向的内存地址,涉及到存储就需要空间,例如在64位程序中,任何一个指针变量都占用64位即8字节的内存空间。而指针所指向的内存空间,指的是根据指针变量中存储的内存地址寻址到对应位置的内存空间。这就好比房间和门牌号的关系,门牌号需要写在一个牌子上,这个牌子就是指针变量所占用的内存空间,而房间本身则是指针变量指向的内存空间。
第二,sizeof关键字的结果是在编译期就计算好的,对于double类型的指针p来说,sizeof(*p)就是sizeof(double),而double类型占用8个字节,这是在编译时就确定的,和p具体指向哪里是完全没有关系的,也就是说在这个程序执行之前,sizeof(*p)就已经确定是8。
“可以*p=5这样赋值”,这是不可能的,原因很简单,double *p只是定义了一个指针变量p,此时变量p中的内容也就是p所指向的地址是完全不可预知的,此时向p所指向的内存空间直接写入数据,是未定义行为,结果是不可预知的,程序很有可能因此崩溃。而malloc的作用,就是向操作系统申请一块可用的内存空间,再令p指向这片内存空间,就可以像其中写入数据了。
温馨提示:答案为网友推荐,仅供参考
第1个回答  2019-01-24
int main(){
    //在栈内存上,int类型,占sizeof(int)=4字节
    int a; 
    
    //在栈内存上,double类型,占sizeof(double)=8字节
    double b; 
    
    //指针变量p在栈内存上,占sizeof(double*)字节,32位程序是4,64位程序是8
    //p本身是一个变量,指针类型的变量,其值是一个整数,是用来存放虚拟地址的。
    double *p; //没有初始化
    
    //sizeof操作符是针对类型求占用字节数,因p是double *类型,
    //所以*p是double类型,sizeof(*p)实际上是sizeof(double)=8
    printf("%d",sizeof(*p)); //8
    
    *p = 5; //运行时错误,p没有指向一个合法的地址空间,非法操作。
    
    p = &b; //正确,p指向栈内存上的b变量
    
    *p = 5; //正确,p指向b,此句执行后b的值也是5
    
    printf("%lf,lf",*p,b); // 5.0,5.0
    
     
    //修改p的指向,malloc在堆内存上申请了8字节,并把首地址赋给了q,
    //即p指向malloc从堆内存申请来的8字节,不再指向b
    p = (double*)malloc(sizeof(double));
    
    *p = 10; //正确
    
    printf("%lf,lf",*p,b); // 10.0,5.0
    
    //释放p指向的堆内存8字节
    free(p); 
    
    //运行时错误,p为野指针,没有指一个向合法地址,非法操作
    *p = 10; 
    
    //正确,p指向虚拟地址0,也是空指针
    p = 0; 
    
    //运行时错误,不能对0地址上的字节赋值。
    *p = 10; 
    
    //正确,p指向虚拟地址100 
    p = 100; 
    
    //可能运行时错误,没法保证此时虚拟地址100一定存在,内存访问违规
    *p = 10; 
    
    printf("%d",p); // 正确,100
    
    //综上,关键是理解并区分指针变量本身和它指向的地址上的数据。
}

第2个回答  2019-01-24
double *p中p变量中存储的是内存地址值,这个地址值是8个字节;
malloc是将运行栈中一块未经使用的空间的首地址返回,并将这个空间标记为已用,你对这个空间内容的操作都是通过这个首地址进行的,首地址的数值对应于你的例子中p的内容;
double *p=5或者p=5,是人为指定内存地址值5,在不清楚5这个地址下的内存空间中存储的内容是什么或有什么作用的情况下,就对这个空间进行操作是逻辑错误,多数情况会导致程序崩溃。本回答被提问者采纳
第3个回答  2019-01-24
type * p;这句话是分配了一个变量p,这个变量可以保存地址,这个地址是一个type类型的存储单元,分配给p的是一个指针类型的存储单元,比如通常是一个unsigned int类型的单元用于存放地址;并且其中的内容没有被初始化,也就是地址不明,p在此时无法直接使用。
通常用法:
double a; //自定义一个double类型存储单元,其别名为a,地址未知
double *p; //自定义一个指针变量p,可以用于指向double型的存储单元
p=&a; //让系统计算变量a的地址赋值给变量p,则可以操作p指向的单元,也就是a变量的单元了
*p=1.0; //相当于a=1.0
相似回答