标题:求助:使用malloc函数构造结构体时 sizeof()函数中写“结构体名”和写“结构 ...
只看楼主
yf19863
Rank: 1
等 级:新手上路
帖 子:10
专家分:0
注 册:2016-10-7
结帖率:100%
已结贴  问题点数:20 回复次数:14 
求助:使用malloc函数构造结构体时 sizeof()函数中写“结构体名”和写“结构体指针”的困惑
如题:使用malloc()函数时,参数为字节数,为了代码的移植性好还是规范性好还是其它的,我们会用sizeof函数。
但是发现用sizeof()函数时,sizeof的参数用 数据类型 和用 数据类型指针 不影响程序运行 。那么问题来了:
假设一个结构体类型是100Byte;但是他的指针是它的首地址,那么还是4Byte;难道在使用malloc动态构造结构体数组
时,系统看到sizeof()函数的参数是一个指针时,还会更深一步的计算?从而得到这个结构体实际的字节数,再赋值给
malloc()函数本身?
/*
    利用结构体来制作简单的学生档案管理
    要求学生对象有三个属性(VB的说法):姓名name、年龄age、成绩score;
    然后依照成绩给学生对象排序输出。
    用函数来实现,不要全部写在main()中
*/

# include <stdio.h>
# include <string.h>
# include <malloc.h>

//定义结构体student
struct student
{
    char name[20];
    int age;
    float score;
};

//主函数入口
int main(void)
{   
    void InputStudent(struct student * pstu,int len);        //函数前置声明:信息输入InputStudent、输出、排序
    void OutputStudent(struct student * pstu,int len);
    void SortStudent(struct student * pstu,int len);
   
    int len;
    printf("Please input the students number:\n");
    printf("Num_Student = ");
    scanf("%d",&len);

    struct student  * stu;        //定义结构体变量
    stu = (struct student * )malloc(len * sizeof(struct student)); //动态构造数组stu ,此处有疑问:sizeof(struct student *)也不影响程序运行
    printf("sizeof(struct student) = %d , sizeof(struct student *) = %d \n",sizeof(struct student),sizeof(struct student *));

    InputStudent(stu,len);        //输入学生信息
    printf("您输入的学生信息为:\n");
    OutputStudent(stu,len);        //输出学生信息以便核对

    printf("\n系统将以学生成绩排序,请稍候......\n");
    SortStudent(stu,len);        //按学生成绩排序(冒泡法)

    printf("学生成绩升序排序后为:\n");
    OutputStudent(stu,len);        //排序后学生信息输出

    return 0;

}

void InputStudent(struct student * pstu,int len)
{
    int i ;

    for(i = 0 ; i < len ; ++i)
    {
        printf("请输入第%d个学生信息:\n",i + 1);
        printf("name = ");
        scanf("%s",pstu[i].name);    //name本身是一个name[30]的字符串数组,前不用加取地址符
        printf("age = ");
        scanf("%d",&pstu[i].age);    //pstu[i]的取地址符容易丢,而且丢了编辑器不报错,程序运行时输入age时就会报错退出了
        printf("score = ");
        scanf("%f",&pstu[i].score);    //取地址符不能丢,同上
    }
}

void OutputStudent(struct student * pstu,int len)
{
    int i = 0 ;
    for(;i < len; ++i)
    {
        printf("Student_%d's :",i + 1);
        printf("name = %s\t age = %d\t score = %.2f\n\n",pstu[i].name,pstu[i].age,pstu[i].score);
    }
}

void SortStudent(struct student * pstu,int len)
{
    int i ,j;
    struct student t;
    for(i = 0; i < len - 1; ++i )
        for(j = 0 ; j < len - 1 - i; ++j)
        {
            if(pstu[j].score > pstu[j + 1].score)
            {   
                t = pstu[j];
                pstu[j] = pstu[j + 1];
                pstu[j + 1] = t;
            }
        }
}

我是新人,也查了一下资料,发现讲的都不太好,也不怎么看得懂。

所以发个贴问一下。
搜索更多相关主题的帖子: 档案管理 结构体 规范性 动态 
2016-11-18 11:39
grmmylbs
Rank: 14Rank: 14Rank: 14Rank: 14
等 级:贵宾
威 望:54
帖 子:1409
专家分:5845
注 册:2016-2-14
得分:5 
sizeof(struct student)申请了28字节的内存,而sizeof(struct student*)只申请4字节内存,但是都会返回一个内存地址给stu。
就像你申请了一块28平米的地,政府给你一个这块地的地址,你盖一个28平房子没问题,如果你只申请了4平米,你盖28平米的房子也能盖,但是你占用了别人家的地了。
别人就有可能会使用你多占的地,修改你的数据。
2016-11-18 12:11
azzbcc
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:江西财经大学
等 级:贵宾
威 望:81
帖 子:3293
专家分:12919
注 册:2012-11-4
得分:5 
调用malloc时,很多时候实际分配的内存会比用户申请的要大一些。

程序代码:
#include <stdio.h>
#include <malloc.h>

//定义结构体student
typedef struct __student_node
{
    char name[20];
    int age;
    float score;
}Student, *pStudent;

int main(void)
{
    size_t len = 67;

    pStudent ps = malloc(len * sizeof(Student));
    pStudent pps = malloc(len * sizeof(pStudent));

    printf("sizeof(Student) = %zu\n", sizeof(Student));
    printf("sizeof(pStudent) = %zu\n", sizeof(pStudent));

    printf("malloc_usable_size(ps) = %zu\n", malloc_usable_size(ps));
    printf("malloc_usable_size(pps) = %zu\n", malloc_usable_size(pps));

    free(ps);
    free(pps);

    return 0;
}


➜  Test gcc --version
gcc (GCC) 6.2.1 20160830
Copyright © 2016 Free Software Foundation, Inc.
本程序是自由软件;请参看源代码的版权声明。本软件没有任何担保;
包括没有适销性和某一专用目的下的适用性担保。
➜  Test gcc main.c -o main
➜  Test ./main
sizeof(Student) = 28
sizeof(pStudent) = 8
malloc_usable_size(ps) = 1880
malloc_usable_size(pps) = 536


[fly]存在即是合理[/fly]
2016-11-18 12:31
yf19863
Rank: 1
等 级:新手上路
帖 子:10
专家分:0
注 册:2016-10-7
得分:0 
回复 2楼 grmmylbs
额,但是如果申请了4平米的话,怎么可以盖28平米呢?
不是函数本身的内存空间,不是不可以读写的吗?
2016-11-18 13:38
yf19863
Rank: 1
等 级:新手上路
帖 子:10
专家分:0
注 册:2016-10-7
得分:0 
回复 3楼 azzbcc
再问个问题,在VC++6.0中,这个例程中:
struct student
{
    char name[20];
    int age;
    int score;   //此处异常,如果改成float score 之后的输入输出修改成 %f 时系统编译正常,运行时错误退出;
};

这个是什么情况 ?难道结构体中不可以使用float或者double两个基本类型?
2016-11-18 14:07
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:5 

如果用结构体指针,只是分配4个字节,运行时也许没有问题,但当用free释放时就会崩溃。free释放只是释放分配大小的空间的4个字节。而那4个字节的空间包含在结构体里面的~试想一下,搬家时只把房子搬走一半,另一半留在原地,那会是怎么样子呢?我也是在
https://bbs.bccn.net/thread-471258-1-1.html
这里发现这个问题的~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-11-18 14:35
grmmylbs
Rank: 14Rank: 14Rank: 14Rank: 14
等 级:贵宾
威 望:54
帖 子:1409
专家分:5845
注 册:2016-2-14
得分:0 
回复 4楼 yf19863
分配空间是统一在堆中申请的,是一大片大家都可以申请的空间。
2016-11-18 16:37
EdmundDantes
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:62
专家分:173
注 册:2016-11-9
得分:5 
回复 4楼 yf19863
不属于你的内存也是可以读写的,你学指针的时候没有越界的情况吗?输出乱码,程序崩溃,这都是越界读写的结果啊。
2016-11-18 16:37
EdmundDantes
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:62
专家分:173
注 册:2016-11-9
得分:0 
我自学的时候也遇到很多这种情况,只要指针指向的地址已分配了内存,不管是几个字节,都可以写入比分配的内存更大的值,写入的时候没有问题,但是读取释放的时候会发生什么事那就不知道了。
2016-11-18 16:40
EdmundDantes
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:62
专家分:173
注 册:2016-11-9
得分:0 
回复 5楼 yf19863
https://support. 这个链接看下
2016-11-18 16:58



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-471296-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.910108 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved