赞
踩
本文主要讲解c语言编程中常用的函数的语法和使用示例,主要有如下函数strncpy、strcmp、memset、strlen、memcp、ioremap、mmap。
strcpy函数的作用是把含有转义字符\0即空字符作为结束符,然后把src该字符串复制到dest,且返回值的类型为“char*”;strcpy是“string copy”(字符串复制)的缩写。
char *strcpy(char *dest, const char *src)
src字符串赋值给dest时,遇到转义字符\0即空字符后面便不再继续输出。如果转义字符在开始定义的时候设置给dest后面也是一样不再继续输出
char dest[6] = "Hello";
char src[20] = "World\0Hi";
strcpy(dest, src);
printf("将src的字符串赋值到dest:%s\n",dest);
strcpy只是复制字符串,但不限制复制的数量,很容易造成缓冲溢出。strncpy要安全一些。
//语法:
char *strncpy(char *destinin, char *source, int maxlen);
//参数:
destinin:表示复制的目标字符数组;
source:表示复制的源字符数组;
maxlen:表示复制的字符串长度。
这里面只能比较字符串,根据对比结果返回值,返回值参考下面strncmp函数;
strcmp(const char *s1,const char * s2);
strncmp函数为字符串比较函数,字符串大小的比较是以ASCII 码表上的顺序来决定,此顺序亦为字符的值。
int strncmp ( const char * str1, const char * str2, size_t n );
功能是把 str1 和 str2 进行比较,最多比较前 n 个字节,若str1与str2的前n个字符相同,则返回0;若s1大于s2,则返回大于0的值;若s1 小于s2,则返回小于0的值。
memset 一般使用“0”初始化内存单元,而且通常是给数组或结构体进行初始化。一般的变量如 char、int、float、double 等类型的变量直接初始化即可,没有必要用 memset。如果用 memset 的话反而显得麻烦。
当然,数组也可以直接进行初始化,但 memset 是对较大的数组或结构体进行清零初始化的最快方法,因为它是直接对内存进行操作的。
# include <string.h>
void *memset(void *s, int c, unsigned long n);
char str[10];
char *p = str;
memset(str, 0, sizeof(str)); //只能写sizeof(str), 不能写sizeof(p)
strlen函数计算字符串中的元素数,即从数组头开始计数,直到满足字符串结束符\0,计数结果不包括\0。
//语法
unsigned int strlen(char *s);
char *p = "this is for testing"; //定义字符串:
strlen(p);
//返回的结果就是p中元素的个数,即19。
需要注意的是,strlen并不是绝对安全的,如果在传入的字符数组的合法范围内,不存在结束符\0,那么strlen函数会一直访问下去,超出数组范围,即出现越界访问。
其他示例:
char *str1 = "abcdef"; // 定义一个字符指针
char str2[] = "abcdef"; // 定义一个字符数组
int len = strlen(str1); // 统计str1字符的个数,结果为6
int len = strlen(str2); // 统计str2字符的个数,结果为6
由src指向地址为起始地址的连续n个字节的数据复制到以dest指向地址为起始地址的空间内,是用指针进行操作的。
void *memcpy(void*dest, const void *src, size_t n);
//source和destin所指内存区域不能重叠,函数返回指向destin的指针。
memcpy和strcpy的对比:
1、与strcpy相比,memcpy并不是遇到’\0’就结束,而是一定会拷贝完n个字节。
2、strcpy提供了字符串的复制。即strcpy只用于字符串复制,并且它不仅复制字符串内容之外,还会复制字符串的结束符。
3、memcpy提供了一般内存的复制。即memcpy对于需要复制的内容没有限制,因此用途更广。
注意:
整型数组复制的时候,第三个参数应该为sizeof(int) * size (同理会有sizeof(long int) * *size, sizeof(Node) * size…)
在memcpy的源码中可以看到,复制是以char为地址单元进行的,所以第三个参数只传进size的话,那么将会只复制前size个char地址单元的数据,具体可以参考下面的示例:*
int main()
{
int a[4] = {1, 2, 3, 100};
int b[3] = {4, 5, 6};
memcpy(b, a, 4); // 通常int = 4 * char, 所以复制的结果为b = {1, 5, 6}, 只复制了前4个char地址的内容
memcpy(b, a, sizeof(int) * 3); // 这里的sizeof(int) * 3 == 12, 所以复制结果为b = {1, 2, 3};
for (int i = 0; i < 3; i++) {
printf("%d ", b[i]);
}
return 0;
}
ioremap函数用来将I/O内存资源的物理地址映射到核心虚地址空间(3GB-4GB)中(这里是内核空间),理论上讲我们就可以象读写RAM那样直接读写I/O内存资源了。
void iomem * ioremap(unsigned long phys_addr, size_t size, unsigned long flags);
参数:
phys_addr:要映射的起始的IO地址
size:要映射的空间的大小
flags:要映射的IO空间和权限有关的标志
该函数返回映射后的内核虚拟地址(3G-4G). 接着便可以通过读写该返回的内核虚拟地址,去访问之这段I/O内存资源
读写I/O的函数如下所示:
a – writel()
writel()往内存映射的 I/O 空间上写数据,wirtel() I/O 上写入 32 位数据 (4字节)。
原型:void writel (unsigned char data , unsigned int addr )
b – readl()
readl() 从内存映射的 I/O 空间上读数据,readl 从 I/O 读取 32 位数据 ( 4 字节 )。
原型:unsigned char readl (unsigned int addr )
mmap函数是一个比较神奇的函数,它可以把文件映射到进程的虚拟内存空间。通过对这段内存的读取和修改,可以实现对文件的读取和修改,而不需要用read和write函数。
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
在这个函数原型中:
参数addr:指定映射的起始地址,通常设为NULL,由内核来分配
参数length:代表将文件中映射到内存的部分的长度。
参数prot:映射区域的保护方式。可以为以下几种方式的组合:
PROT_EXEC 映射区域可被执行
PROT_READ 映射区域可被读取
PROT_WRITE 映射区域可被写入
PROT_NONE 映射区域不能存取
参数flags:映射区的特性标志位,常用的两个选项是:
MAP_SHARD:写入映射区的数据会复制回文件,且运行其他映射文件的进程共享
MAP_PRIVATE:对映射区的写入操作会产生一个映射区的复制,对此区域的修改不会写回原文件;
参数fd:要映射到内存中的文件描述符,有open函数打开文件时返回的值。
参数offset:文件映射的偏移量,通常设置为0,代表从文件最前方开始对应,offset必须是分页大小的整数倍。
函数返回值:实际分配的内存的起始地址。
示例代码:
//打开文件
fd = open("testdata",O_RDWR);
//创建mmap
start = (char *)mmap(NULL,128,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
//读取文件
strcpy(buf,start);
printf("%s\n",buf);
//写入文件
strcpy(start,"Write to file!\n");
ioremap和mmap的对比:
ioremap是将物理地址转换为虚拟地址
mmap是将设备内存线性地址映射到用户地址空间
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。