printf,scanf、malloc、realloc、calloc(与c++的new的区别)的各种用法

printf,scanf、malloc、realloc、calloc(与c++的new的区别)的各种用法

printf、scanf:

  • printf()函数是格式化输出函数, 一般用于向标准输出设备按规定格式输出信息。
    printf()函数的调用格式为: printf(“<格式化字符串>”, <参量表>)。
    格式输出,它是c语言中产生格式化输出的函数(在 stdio.h 中定义)。用于向终端(显示器、控制台等)输出字符。格式控制由要输出的文字和数据格式说明组成。要输出的的文字除了可以使用字母、数字、空格和一些数字符号以外,还可以使用一些转义字符表示特殊的含义。
    具体格式:
    int i, j;
    scanf(“%d, %d”, &i, &j);
    printf(“i=%d;j=%d”, i, j);
    return 0;

    or:
    printf(“百度百科”);
    return 0;

  • 与printf函数一样,都被定义在头文件stdio.h里,因此在使用scanf函数时要加上#include

malloc、realloc、calloc:

  • malloc:

函数声明(函数原型):

void *malloc(int size);

说明:malloc 向系统申请分配指定size个字节的内存空间。返回类型是 void* 类型。void* 表示未确定类型的指针。C,C++规定,void* 类型可以强制转换为任何其它类型的指针。
从函数声明上可以看出。malloc 和 new 至少有两个不同: new 返回指定类型的指针,并且可以自动计算所需要大小。比如:

int *p;

p = new int; //返回类型为int* 类型(整数型指针),分配大小为 sizeof(int);

或:

int* parr;

parr = new int [100]; //返回类型为 int* 类型(整数型指针),分配大小为 sizeof(int) * 100;

而 malloc 则必须由我们计算要字节数,并且在返回后强行转换为实际类型的指针。

int* p;

p = (int *) malloc (sizeof(int));

第一、malloc 函数返回的是 void * 类型,如果你写成:p = malloc (sizeof(int)); 则程序无法通过编译,报错:“不能将 void* 赋值给 int * 类型变量”。所以必须通过 (int *) 来将强制转换。

第二、函数的实参为 sizeof(int) ,用于指明一个整型数据需要的大小。如果你写成:

int* p = (int *) malloc (1);

代码也能通过编译,但事实上只分配了1个字节大小的内存空间,当你往里头存入一个整数,就会有3个字节无家可归,而直接“住进邻居家”!造成的结果是后面的内存中原有数据内容全部被清空。

malloc 也可以达到 new [] 的效果,申请出一段连续的内存,方法无非是指定你所需要内存大小。

比如想分配100个int类型的空间:

int* p = (int ) malloc ( sizeof(int) 100 ); //分配可以放得下100个整数的内存空间。

另外有一点不能直接看出的区别是,malloc 只管分配内存,并不能对所得的内存进行初始化,所以得到的一片新内存中,其值将是随机的。

除了分配及最后释放的方法不一样以外,通过malloc或new得到指针,在其它操作上保持一致。

  • 总:
    realloc
    原型:extern void *realloc(void *mem_address, unsigned int newsize);
    用法:#include <stdlib.h> 有些编译器需要#include <alloc.h>
    功能:改变mem_address所指内存区域的大小为newsize长度。
    说明:如果重新分配成功则返回指向被分配内存的指针,否则返回空指针NULL。
    当内存不再使用时,应使用free()函数将内存块释放。
    注意:这里原始内存中的数据还是保持不变的。
    举例:
    // realloc.c
#include <syslib.h>
#include <alloc.h>
main()
{
char *p;
clrscr(); // clear screen
p=(char *)malloc(100);
if(p)
printf("Memory Allocated at: %x",p);
else
printf("Not Enough Memory!/n");
getchar();
p=(char *)realloc(p,256);
if(p)
printf("Memory Reallocated at: %x",p);
else
printf("Not Enough Memory!/n");
free(p);
getchar();
return 0;
}

详细说明及注意要点:
1、如果有足够空间用于扩大mem_address指向的内存块,则分配额外内存,并返回mem_address
这里说的是“扩大”,我们知道,realloc是从堆上分配内存的,当扩大一块内存空间时, realloc()试图直接从堆上现存的数据后面的那些字节中获得附加的字节,如果能够满足,自然天下太平。也就是说,如果原先的内存大小后面还有足够的空闲空间用来分配,加上原来的空间大小= newsize。那么就ok。得到的是一块连续的内存。
2、如果原先的内存大小后面没有足够的空闲空间用来分配,那么从堆中另外找一块newsize大小的内存。
并把原来大小内存空间中的内容复制到newsize中。返回新的mem_address指针。(数据被移动了)。
老块被放回堆上。
例如:

#include <malloc.h>
char *p,*q;
p = (char * ) malloc (10);
q=p;
p = (char * ) realloc (p,20);

…………………………
这段程序也许在编译器中没有办法通过,因为编译器可能会为我们消除一些隐患!在这里我们只是增加了一个记录原来内存地址的指针q,然后记录了原来的内存地址p,如果不幸的话,数据发生了移动,那么所记录的原来的内存地址q所指向的内存空间实际上已经放回到堆上了!这样一来,我们应该终于意识到问题的所在和可怕了吧!
3、返回情况
返回的是一个void类型的指针,调用成功。(这就再你需要的时候进行强制类型转换)
返回NULL,当需要扩展的大小(第二个参数)为0并且第一个参数不为NULL,此时原内存变成了“freed(游离)”的了。
返回NULL,当没有足够的空间可供扩展的时候,此时,原内存空间的大小维持不变。
4、特殊情况
如果mem_address为null,则realloc()和malloc()类似。分配一个newsize的内存块,返回一个指向该内存块的指针。
如果newsize大小为0,那么释放mem_address指向的内存,并返回null。
如果没有足够可用的内存用来完成重新分配(扩大原来的内存块或者分配新的内存块),则返回null.而原来的内存块保持不变。

==============================================================

void* malloc(unsigned size); void* calloc(size_t nelem, size_t elsize); 和void* realloc(void* ptr, unsigned newsize);都在stdlib.h函数库内,是C语言的标准内存分配函数。
1. 函数malloc()和calloc()都可以用来动态分配内存空间。malloc()函数有一个参数,即要分配的内存空间的大小,malloc 在分配内存时会保留一定的空间用来记录分配情况,分配的次数越多,这些记录占用的空间就越多。另外,根据 malloc 实现策略的不同,malloc 每次在分配的时候,可能分配的空间比实际要求的多些,多次分配会导致更多的这种浪费。当然,这些都和 malloc 的实现有关;calloc()函数有两个参数,分别为元素的数目和每个元素的大小,这两个参数的乘积就是要分配的内存空间的大小。如果调用成功,它们都将返回所分配内存空间的首地址。
2. 函数malloc()和函数calloc()的主要区别是前者不能初始化所分配的内存空间,而后者能。
3. realloc可以对给定的指针所指的空间进行扩大或者缩小,无论是扩张或是缩小,原有内存的中内容将保持不变。当然,对于缩小,则被缩小的那一部分的内容会丢失。
4. realloc 并不保证调整后的内存空间和原来的内存空间保持同一内存地址。相反,realloc 返回的指针很可能指向一个新的地址。所以在代码中,我们必须将realloc返回的值,重新赋值给 p :
p = (int *) realloc (p, sizeof(int) *15);

==================================================================
真正认识 realloc 的工作方式。
Posted on 2008-11-20 13:12 啊夏 阅读(142) 评论(0) 编辑 收藏 网摘 所属分类: c/c++

realloc 用过很多次了。无非就是将已经存在的一块内存扩大。

char* p = malloc(1024);
char* q = realloc(p,2048);

现在的问题是我们应该如何处理指针 p。 刚开始按照我最直观的理解,如果就是直接将 p = NULL;。 到最后只需要释放 q的空间就可以了。

因为最近在做个封装。结果在做单元测试的时候发现。有时候我在 free(q); 的时候会出错。这样我就郁闷了。

后来仔细一跟踪,发现 realloc 完以后 q 和 p 的指针地址是一样。不过有时候又不一样。

仔细查了下资料。得到如下信息:

   1.如果 当前连续内存块足够 realloc 的话,只是将p所指向的空间扩大,并返回p的指针地址。 这个时候 q 和 p 指向的地址是一样的。

   2.如果 当前连续内存块不够长度,再找一个足够长的地方,分配一块新的内存,q,并将 p指向的内容 copy到 q,返回 q。并将p所指向的内存空间删除。

这样也就是说 realloc 有时候会产生一个新的内存地址 有的时候不会。所以在分配完成后。我们需要判断下 p 是否等于 q。并做相应的处理。

这里有点要注意的是要避免 p = realloc(p,2048); 这种写法。有可能会造成 realloc 分配失败后,p原先所指向的内存地址丢失。

=========================================

关于realloc函数说明的补充:
函数定义:
void *realloc(void *ptr, size_t size);
上面的分析基本没有问题,但有两点要注意:
1.返回值可能与ptr的值不同,如果是不同的话,那么realloc函数完成后,ptr指向的旧内存已被free掉了。
2。如果返回NULL值,则分配不成功,而原来的ptr指向的内存还没有被free掉,要求程序显式free.

故p = (int *) realloc (p, sizeof(int) *15);语句有这么一个问题,
调用前p指向一个已分配成功的内存,而调用realloc时却失败(即返回NULL),此时,p原来指向的内存还没有free掉,而现在又找不到地址,这样就出现memory leak了。

关于这一点的确要注意,最好如下:
int *q
q = (int *) realloc (p, sizeof(int) *15);

if(!q) p =q;

======================================================

首先看一下下面的C程序片断:

#include <malloc.h>

char  *p;

p = (char * ) malloc (10);

p = (char * ) realloc (p,20);

…………………………

这段程序的意思很简单,只有稍有点C基础的人都可以看懂。函数首先定义了一个字符型的指针p,然后为指针p分配了一个10个字节大小的内存空间,接着将这个内存块的大小增加到20个字节。



这里有什么问题吗?上机运行一下,好像没有问题!



是的,这样上机运行是没有问题的,但是这里存在着也许我们不太注意的隐患!隐患在那里?这就是我在本文中要详细说明的realloc()函数了。



再看一下下面一段来自MSDN的话:

realloc returns a void pointer to the reallocated (and possibly moved) memory block. The return value is NULL if the size is zero and the buffer argument is not NULL, or if there is not enough available memory to expand the block to the given size. In the first case, the original block is freed. In the second, the original block is unchanged. The return value points to a storage space that is guaranteed to be suitably aligned for storage of any type of object. To get a pointer to a type other than void, use a type cast on the return value.

这段E文还不算是晦涩难懂,所以我就不翻译了,大致的意思是说关于realloc返回值的。但是这里对他的返回值分了几种情况:

1、 返回void * 指针,调用成功。

2、 返回NULL,当需要扩展的大小(第二个参数)为0并且第一个参数不为NULL,此时原内存变成了“freed(游离)”的了。

3、 返回NULL,当没有足够的空间可供扩展的时候,此时,原内存空间的大小维持不变。

第一种情况告诉了我们在得到需要的内存空间后需要做类型转换的工作;

第二种情况可能只有傻瓜才会去使用吧!

第三种情况,内存空间不够的时候就会维持未来的大小不变。

    MSDN上面说内存空间不够的时候就不会扩展原来的内存空间的大小,这话固然没有错,但是有点含糊,似乎遗漏了一种情况!我们知道,realloc是从堆上分配内存的,当扩大一块内存空间时, realloc()试图直接从堆上现存的数据后面的那些字节中获得附加的字节,如果能够满足,自然天下太平;可如果数据后面的字节不够的话,问题就出来了,那么就使用堆上第一个有足够大小的自由块,现存的数据然后就被拷贝至新的位置,而老块则放回到堆上。这句话传递的一个重要的信息就是数据可能被移动!看到这里,也许我们已经发现一开始我给出的程序的问题了。为了更清楚地说明问题,可以将上面的程序改成下面的形式:
#include <malloc.h>

char  *p,*q;

p = (char * ) malloc (10);

q=p;

p = (char * ) realloc (p,20);

…………………………

这段程序也许在编译器中没有办法通过,因为编译器可能会为我们消除一些隐患!在这里我们只是增加了一个记录原来内存地址的指针q,然后记录了原来的内存地址p,如果不幸的话,数据发生了移动,那么所记录的原来的内存地址q所指向的内存空间实际上已经放回到堆上了!这样一来,我们应该终于意识到问题的所在和可怕了吧!

malloc与c++中的new的区别:

malloc与new :

1 、new 建立的是一个对象,malloc 分配的是一块内存。
2、malloc申请的是heap区的内存空间,返回的是指针。new 建立的对象你可以把它当成一个普通的对象,用成员函数访问,不要直接访问它的地址空间。(注意用delete释放空间)。
3、malloc/free是C/C++中的方法(函数),new/delete是C++中的操作符。
4、使用free之前要判断,使其free的指针是!NULL的,使用delete则无须判断。
5、free掉的内存是该指针指向的一段内存空间,里面应该是空的。而delete掉的内存是里面确实存有数据或者对象的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值