函数接口
示例代码如下:
man page
http://www.linuxmanpages.com/
NAME
#把一个字符串考贝到另一个字符串
strcpy, strncpy - copy a string
SYNOPSIS
#函数原型
#include <string.h>
#dest 目标字串
#src 源字串
char *strcpy(char *dest, const char *src);
#会把末尾的\n一起考贝到目录字串中
#目标字串空间要足够大,防止越界
#n 指定字节数,如果src不足,则用\0补齐
char *strncpy(char *dest, const char *src, size_t n);
malloc
可以在堆空间内动态分配存(通过brk系统向操作系统申请内存)
free
动态分配内存后,可通过free系释放内存
函数原型
NAME
calloc, malloc, free, realloc - Allocate and free dynamic memory
SYNOPSIS
#include <stdlib.h>
#成功返回分配内存空间的首地址,出错返回NULL
void *calloc(size_t nmemb, size_t size);
#size 表示要分配的字节数
void *malloc(size_t size);
void free(void *ptr);
void *realloc(void *ptr, size_t size);
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
int number;
char *msg;
} unit_t;
int main(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!");
printf("number: %d\n msg: %s\n",p->number,p->msg);
//释放空间
free(p->msg);
free(p);
p=NULL;
return 0;
}
传入和传出参数
传入参数示例:
void func(const unit_t *p);
传出参数示例:
void func(unit_t *p);
/*populator.h*/
#ifndef POPULATOR_H
#define POPULATOR_H
typedef struct{
int number;
char msg[20];
}unit_t;
extern void set_unit(unit_t *);
#endif
/*populator.c*/
#include <string.h>
#include "populator.h"
void set_unit(unit_t *p){
if(p==NULL){
return;
}
p->number=3;
strcpy(p->msg,"Hello world!");
}
/*main.c*/
#include <stdio.h>
#include "populator.h"
int main(void){
unit_t u;
set_unit(&u);
printf("number: %d\n msg: %s\n",u.number,u.msg);
return 0;
}
运行结果:
yuezhenhua@ubuntu:/opt/sdk/tc/value_result$ gcc populator.c main.c -o main
yuezhenhua@ubuntu:/opt/sdk/tc/value_result$ ./main
number: 3
msg: Hello world!
两层指针的参数:
用两层指针作传出参数的系统函数:pthread_join(3)
示例代码如下:
/*redirect_ptr.h*/
#ifdef REDIRECT_PTR_H
#define REDIRECT_PTR_H
/*传出参数*/
extern void get_a_day(const char **);
#endif
示例代码如下:
#ifndef REDIRECT_PTR_H
#define REDIRECT_PTR_H
extern void get_a_day(const char **);
#endif
#include "redirect_ptr.h"
static const char *msg[]={"sunday","monday","tuesday","wednesday","thursday","friday","saturday"};
void get_a_day(const char **pp){
static int i=0;
*pp=msg[i%7];
i++;
}
#include <stdio.h>
#include "redirect_ptr.h"
int main(void){
const char *firstday=NULL;
const char *secondday=NULL;
get_a_day(&firstday);
get_a_day(&secondday);
printf("%s\t%s\n",firstday,secondday);
return 0;
}
运行结果如下:
yuezhenhua@ubuntu:/opt/sdk/tc/value_result_doublepoint$ ./main
sunday
monday
两层指针作为传出参数,可以在函数中分配内存,调用者通过传出参数取得指向该内存的指什
void alloc_unit(unit_t **pp);
void free_unit(unit_t *p);
通过两层指针参数分配内存
示例代码如下:
#ifndef PARA_ALLOCATOR_H
#define PARA_ALLOCATOR_H
typedef struct{
int number;
char *msg;
}unit_t;
extern void alloc_unit(unit_t **);
extern void free_unit(unit_t *);
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "para_allocator.h"
void alloc_unit(unit_t **pp){
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!");
*pp=p;
}
void free_unit(unit_t *p){
free(p->msg);
free(p);
}
#include <stdio.h>
#include "para_allocator.h"
int main(void){
unit_t *p=NULL;
alloc_unit(&p);
printf("number: %d\nmsg:%s\n",p->number,p->msg);
free_unit(p);
p=NULL;
return 0;
}
运行结果:
yuezhenhua@ubuntu:/opt/sdk/tc/double_point_malloc$ gcc para_allocator.c main.c -o main
yuezhenhua@ubuntu:/opt/sdk/tc/double_point_malloc$ ./main
number: 3
msg:Hello world!
返回值是指针的情况:
同两层指针相同也分两种情况:
1 传出指向静态内存或已分配的动态内存的指针
2 在函数中动态分配内存,并动态传出指向这块内存的指针
返回已分配内存的指针
示例代码如下:
#ifndef RET_PTR_H
#define RET_PTR_H
extern char *get_a_day(int idx);
#endif
#include <string.h>
#include "ret_ptr.h"
static const char *msg[]={"sunday","monday","tuesday","wednesday","thursday","friday","saturday"};
char *get_a_day(int idx){
static char buf[20];
strcpy(buf,msg[idx]);
return buf;
}
#include <stdio.h>
#include "ret_ptr.h"
int main(void){
printf("%s %s\n",get_a_day(0),get_a_day(1));
return 0;
}
运行结果如下:
yuezhenhua@ubuntu:/opt/sdk/tc/point_result$ gcc ret_ptr.c main.c -o main
yuezhenhua@ubuntu:/opt/sdk/tc/point_result$ ./main
sunday sunday
动态分配内存并返回指针示例
通过返回值分配内存只需要一层指针,让实现者去调用,称为callback function
void func(void(*f)(void *),void *p);
回调函数
如果参数是一个函数指针,调用者可以传递一个函数的地址给实现者
示例代码如下:
#ifndef PARA_CALLBACK_H
#define PARA_CALLBACK_H
typedef void (*callback_t) (void *);
extern void repeat_three_times(callback_t,void *);
#endif
#include "para_callback.h"
void repeat_three_times(callback_t f,void *para){
f(para);
f(para);
f(para);
}
#include <stdio.h>
#include "para_callback.h"
void say_hello(void *str){
printf("Hello %s\n",(const char *) str);
}
void count_numbers(void *num){
int i;
for(i=1;i<=(int)num;i++){
printf("%d ",i);
}
putchar('\n');
}
int main(void){
repeat_three_times(say_hello,"yue");
repeat_three_times(count_numbers,(void *)4);
return 0;
}
运行结果:
yuezhenhua@ubuntu:/opt/sdk/tc/callback_function$ gcc para_callback.c main.c -o main
yuezhenhua@ubuntu:/opt/sdk/tc/callback_function$ ./main
Hello yue
Hello yue
Hello yue
1 2 3 4
1 2 3 4
1 2 3 4
泛型算法generic
#ifndef GENRICS_H
#define GENRICS_H
typedef int(*cmp_t)(void *,void *);
extern void *max(void *data[],int num,cmp_t cmp);
#endif
#include "generics.h"
void *max(void *data[],int num,cmp_t cmp){
int i;
void *temp=data[0];
for(i=0;i<num;i++){
if(cmp(temp,data[i]<0)){
temp=data[i];
}
}
return temp;
}
#include <stdio.h>
#include "generics.h"
typedef struct{
const char *name;
int score;
}student_t;
int cmp_student(void *a,void *b){
if(((student_t *)a)->score>((student_t *)b)->score){
return 1;
}else if(((student_t *)a)->score==((student_t *)b)->score){
return 0;
}else{
return -1;
}
}
int main(void){
student_t list[4]={{"tom",68},{"jerry",72},{"moby",60},{"kirby",89}};
student_t *plist[4]={&list[0],&list[1],&list[2],&list[3]};
student_t *pmax=max((void **)plist,4,cmp_student);
printf("%s gets the highest score %d\n",pmax->name,pmax->score);
return 0;
}
可变参数
int printf(const char *format,...);
实现一个简单的myprintf函数
#include <stdio.h>
#include <stdarg.h>
void myprintf(const char *format,...){
va_list ap;
char c;
va_start(ap,format);
while(c=*format++){
switch(c){
case 'c':{
char ch=va_arg(ap,int);
putchar(ch);
break;
}
case 's':{
char *p=va_arg(ap,char *);
fputs(p,stdout);
break;
}
default:{
putchar(c);
}
}
va_end(ap);
}
}
int main(void){
myprintf("c\ts\n",'1',"hello");
return 0;
}
反汇编结果
objdump -dS a.out
检查可变参数的个数
#include <stdio.h>
#include <stdarg.h>
void printlist(int begin,...){
va_list ap;
char *p;
va_start(ap,begin);
p=va_arg(ap,char *);
while(p!=NULL){
fputs(p,stdout);
putchar('\n');
p=va_arg(ap,char *);
}
va_end(ap);
}
int main(){
printlist(0,"hello","world","foo","bar",NULL);
return 0;
}