1. strcpy与strncpy
#include <string.h>
char *strcpy(char *dest, const char *src);
chasr *strncpy(char *dest, const char *src, size_t n);
把src所指向的字符串copy到des所指向的内存空间,看参数也知道,因为dest是char*类型的,而src是const char*,说明src所只相当内存空间在函数中只能读不能改写,而dest所指向的内存空间在函数中是可以改写的
Eg: char buf[10];
strcpy(buf,”hello”;)
printf(buf);
strcpy在copy字符串时会把结尾的’\0’也复制到dest中,因此保证了dest中是以’\0’结尾的字符串,但是,strcpy只知道src字符串的首地址,不知道长度,它会一直拷贝到’\0’为止,所以dest所指向的内存空间要足够大,否则可能写越界
char *strncpy(char *dest,const char *src,size_t n)
{
size_t i;
for(i+0;i<n&&src[i]!=’\0’;i++)
dest[i]=src[i];
for(;i<n;i++)
dest[i]=’\0’;
return dest;
}
Strncpy可以用截断的方式保证写不越界,但是有可能产生读越界
char buf[10];
strncpy(buf,”hello world”,sizeof(buf));
buf[sizeof(buf)-1]=’\0’;
2. malloc与free
c标准库函数malloc可以在堆空间动态分配内存,它的底层
它的底层通过brk系统调用像操作系统申请内存。动态分配的内存用完之后可以用free释放,癸亥给malloc,这样下次调用malloc时可以再次被分配
#include <stdio.h>
Void *malloc(size_t,size);
//成功返回所分配内存空间的首地址,出错返回NULL
Void free(void *ptr);
内存泄露:每次分配完了不释放,导致最后内存耗尽
Void foo(void)
{
char *p =malloc(10);
…
}
foo函数返回时要释放局部变量p的内存空间,它所指向的内存地址就丢失了,这10个字节也就没法释放了。一定要保存好malloc返回的指针。
3. 传入参数与传出参数
如果函数借口有指针参数,可以把指针所指向的数据传给函数使用,称为传入参数,也可以由函数填充指针所指的内存空间,传回给调用者使用,称为传出参数
传入参数示例:
void func(const unit_t *p)
调用者:
(1) 分配p所指的内存空间
(2) 在p所指的内存空间中保存数据
(3) 调用函数
(4) 由于有const限定符,调用者可以确信p所指的内存空间不会被改变
实现者:
(1) 指定指针参数的类型unit_t *
(2) 读取p所指的内存空间
传出参数示例:
调用者:
(1) 分配p所指的内存空间
(2) 调用函数
(3) 读取p所指的内存空间
实现者:
(1) 规定指针参数的类型unit_t *
(2) 在p所指的内存空间中保存数据
4. 两层指针的参数
5. 返回值是指针的情况
返回指向已分配内存的指针示例:unit_t *func(void)
调用者:
(1) 调用函数
(2) 将返回值保存下来以备后用
实现者
(1) 规定返回值指针的类型unit_t *
(2) 返回一个指针
动态分配内存并返回指针
//ret_allocator.h
#ifndef RET_ALLOCATOR_H
#define RET_ALLOCATOR_H
typedef struct{
int number;
char *msg;
} unit_t;
extern unit_t *alloc_unit(void);
extern void free_unit(unit_t *);
#endif
//ret_allocator.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include “ret_allocator.h”
unit_t *alloc_unit(void)
{
unit_t *p=malloc(sizeof(unit_t));
if(p==NULL){
printf(“out of memory\n”);
exit(1);
}
p->number=3;
p->msg=malloc(20);
strcpy(p->msg,”hello world!”);
return p;
}
void free_unit(unit_t *p)
{
free(p->msg);
free(p);
}
//main.c
#include <stdio.h>
#include “ret_allocator.h”
Int main(void){
unit_t *p=alloc_unit();
printf(“number:%d\nmsg:%s\n”,p->number,p->msg);
free_unit(p);
p=NULL;
return 0;
}
6. 回调函数
如果参数是一个函数指针,调用者可以传递一个函数的地址给实现者,让实现者去调用它,
这叫做回调函数callback fuction
示例:void func(void(*f)(void *),void *p);
调用者:
(1) 提供一个回调函数,再提供一个准备传给回调函数的参数
(2) 把回调函数传给参数f,把准备传给回调函数的参数按void *类型传给参数p
实现者:
在适当的时候根据调用者传来的函数指针f调用回调函数,将调用者传来的参数p转交给回调函数,就是调用f(p);