memset+strcpy+strncpy的函数详解以及字符数组输出的特殊情况
2016-03-01 02:13
330 查看
memset:
头文件:#include在<string.h>
原型: void *memset(void *s, int c, size_t n);
将已开辟内存空间的s所指向的每一块内存中的每一个字节全部设定为c为ASCII码!!!
The memset() function fills the first n bytes of the memory area pointed to by s with the constant byte c
原型函数:
void* memset(void* s, int c, size_t n){
unsigned char* p = (unsigned char*) s;
while (n > 0) {
*p++ = (unsigned char) c;
--n;
}
return s;
}
1, memset常被用来做初始化数组
#include <stdio.h>
#include <string.h>
int main()
{
int i;
char p[5];
for(i = 0; i<5;i++){
printf("%c\n", p[i]);
}
return 0;
}
运行结果:
可以看到我们的中的p[5]数组没有初始化的话,会得到一些奇怪的东西,则可能会导致我们程序的错误运行,如果我们不初始化的话!!!
为了避免这种情况,我们可以加入:
memset(p, '0', strlen(p));
for(i = 0; i<5;i++){
printf("%c\n", p[i]);
}
这样,我们看的话,就可以得到正确的结果了,
但是要注意的是,memset的第二个参数是char类型的
如果写成这样:memset(p, 0 , strlen(p))
那么得到的结果是:什么也看不到,只是因为0对应的ascii码是空格,而‘0’对应的是48
程序二:
#include <stdio.h>
#include <string.h>
int main()
{
int i;
char p[5] = "1234";
p[4] = 0;
printf("%c %d\n", p[4], p[4]);
p[2] ='0';
printf("%c %d\n", p[2], p[2]);
printf("after:%s\n", p);
return 0;
}运行结果:
可以看出,我们先将p[4]赋值为0,从输出结果可以直观的看到:p [4]的字符输出为空格,整形输出为0
p[2]赋值为字符0,字符输出为0,整形输出为48
值得我们注意的是:
有些特殊的赋值,如:
p[3] = 0;
printf("%c %d\n", p[3], p[3]);
输出:
0
0 48
after:120
p[3] = ‘\n’;
printf("%c %d\n", p[3], p[3]);输出:
10
0 48
after:120
p[3] = ‘ ’; //赋值一个空格
printf("%c %d\n", p[3], p[3]);输出:
32
0 48
after:120
p[3] = ‘\t’;
printf("%c %d\n", p[3], p[3]);输出:
9
0 48
after: 120
可以看出对于字符数组以格式化输出时:当碰到ascii为0,空格(ascii为32),换行符(ascii为10),tab键(ascii为9)都会输出停止的
还有就是:
char p[5] = "1234";
p[4] = 0;
printf("%c %d\n", p[4], p[4])与
char *p = "1234";
p[4] = 0;
printf("%c %d\n", p[4], p[4]);当我们运行第一个的时候,是没有问题的,可以得到一定的结果
但是,当我们运行第二个程序的时候,运行是会出错,显示段错误 (核心已转储)
分析可知,是因为p所指向的是一个常量字符串,不可以直接或者简介的改变里面的内容
转为正题:
2,这个函数也多用于socket中用于清空数组,如我们经常这样用:memset(buffer, 0, sizeof(buffer))
而且这个函数还方便的用于清空结构类型的数组或变量(转:)
struct sample_struct
{
char csName[16];
int iSeq;
int iType;
};
对于变量:
struct sample_strcut stTest;
一般情况下,清空stTest的方法:
stTest.csName[0]='/0';
stTest.iSeq=0;
stTest.iType=0;
用memset就非常方便:
memset(&stTest,0,sizeof(struct sample_struct));
如果是数组:
struct sample_struct TEST[10];
则
memset(TEST,0,sizeof(struct sample_struct)*10);
3, 参数问题:
#include <stdio.h>
#include <string.h>
int main()
{
char p[5];
p[3] = 'a';p[4]= 'b';
memset(p, '0' , 3);
printf("%s ,\n", p);
return 0;
}
运行结果:
看得出来,对于memset置0的时候,只对前三项初始化了,所以他们不影响后面两项,至于输出结果后面出现的(007f),则应该是对于上面这种把p的内存数限定的情况下,但是在结束的时候还没有找到退出的条件的,(即上面提到的几种情况)
char p[5] ;
printf("%s ,\n", p);多次运行结果如下:
strcpy:
头文件:#include <string.h>
char *strcpy(char *dest,char *src);把从src地址开始且含有NULL结束符的字符串赋值到以dest开始的地址空间,返回dest(地址中存储的为复制后的新值)。要求:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串
源文件:
char *strcpy(char *strDest, const char *strSrc);//strDest为目标,strSrc为源
{
assert((strDest!=NULL) && (strSrc !=NULL)); //如果两个为空则不用复制,直接中止
char *address = strDest; //用address指向strDest开始地址
while( (*strDest++ = * strSrc++) != ‘\0’ ) //复制,直到源串结束;
NULL ; //空操作
return address ; //返回strDest开始地址
}
}如:
char a[50], b[100];
strcpy(a, b,)这里将b的内容赋值给a,如果b中的(‘\0’)出现在前50个里面,那么就没有问题,如果在50个以后,那么就会造成内存泄露
这里,提一下:memcpy和strcpy的区别(转自:http://www.cnblogs.com/stoneJin/archive/2011/09/16/2179248.html)
strcpy和memcpy都是标准C库函数,它们有下面的特点。
strcpy提供了字符串的复制。即strcpy只用于字符串复制,并且它不仅复制字符串内容之外,还会复制字符串的结束符。
已知strcpy函数的原型是:char* strcpy(char* dest, const char* src);
memcpy提供了一般内存的复制。即memcpy对于需要复制的内容没有限制,因此用途更广。
void *memcpy(void *memTo, const void *memFrom, size_t size)
{
if((memTo == NULL) || (memFrom == NULL)) //memTo和memFrom必须有效
return NULL;
char *tempFrom = (char *)memFrom; //保存memFrom首地址
char *tempTo = (char *)memTo; //保存memTo首地址
while(size -- > 0 && *tempFrom++!='\0') //循环size次,复制memFrom的值到memTo中
*tempTo++ = *tempFrom++ ;
return memTo;
}
strcpy和memcpy主要有以下3方面的区别。
1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy
程序4:
#include <stdio.h>
#include <string.h>
int main()
{
char a[5]= "1234";
char b[5]= "abcd";
b[3]= '\0';
strcpy(a, b);
printf("%s\n", a);
memcpy(a, b, 5);
printf("%s\n", a);
return 0;
}
运行结果:
abc
abc
可以看出:两者的赋值都是碰到('\0')就退出
头文件:#include在<string.h>
原型: void *memset(void *s, int c, size_t n);
将已开辟内存空间的s所指向的每一块内存中的每一个字节全部设定为c为ASCII码!!!
The memset() function fills the first n bytes of the memory area pointed to by s with the constant byte c
原型函数:
void* memset(void* s, int c, size_t n){
unsigned char* p = (unsigned char*) s;
while (n > 0) {
*p++ = (unsigned char) c;
--n;
}
return s;
}
1, memset常被用来做初始化数组
#include <stdio.h>
#include <string.h>
int main()
{
int i;
char p[5];
for(i = 0; i<5;i++){
printf("%c\n", p[i]);
}
return 0;
}
运行结果:
可以看到我们的中的p[5]数组没有初始化的话,会得到一些奇怪的东西,则可能会导致我们程序的错误运行,如果我们不初始化的话!!!
为了避免这种情况,我们可以加入:
memset(p, '0', strlen(p));
for(i = 0; i<5;i++){
printf("%c\n", p[i]);
}
这样,我们看的话,就可以得到正确的结果了,
但是要注意的是,memset的第二个参数是char类型的
如果写成这样:memset(p, 0 , strlen(p))
那么得到的结果是:什么也看不到,只是因为0对应的ascii码是空格,而‘0’对应的是48
程序二:
#include <stdio.h>
#include <string.h>
int main()
{
int i;
char p[5] = "1234";
p[4] = 0;
printf("%c %d\n", p[4], p[4]);
p[2] ='0';
printf("%c %d\n", p[2], p[2]);
printf("after:%s\n", p);
return 0;
}运行结果:
可以看出,我们先将p[4]赋值为0,从输出结果可以直观的看到:p [4]的字符输出为空格,整形输出为0
p[2]赋值为字符0,字符输出为0,整形输出为48
值得我们注意的是:
有些特殊的赋值,如:
p[3] = 0;
printf("%c %d\n", p[3], p[3]);
输出:
0
0 48
after:120
p[3] = ‘\n’;
printf("%c %d\n", p[3], p[3]);输出:
10
0 48
after:120
p[3] = ‘ ’; //赋值一个空格
printf("%c %d\n", p[3], p[3]);输出:
32
0 48
after:120
p[3] = ‘\t’;
printf("%c %d\n", p[3], p[3]);输出:
9
0 48
after: 120
可以看出对于字符数组以格式化输出时:当碰到ascii为0,空格(ascii为32),换行符(ascii为10),tab键(ascii为9)都会输出停止的
还有就是:
char p[5] = "1234";
p[4] = 0;
printf("%c %d\n", p[4], p[4])与
char *p = "1234";
p[4] = 0;
printf("%c %d\n", p[4], p[4]);当我们运行第一个的时候,是没有问题的,可以得到一定的结果
但是,当我们运行第二个程序的时候,运行是会出错,显示段错误 (核心已转储)
分析可知,是因为p所指向的是一个常量字符串,不可以直接或者简介的改变里面的内容
转为正题:
2,这个函数也多用于socket中用于清空数组,如我们经常这样用:memset(buffer, 0, sizeof(buffer))
而且这个函数还方便的用于清空结构类型的数组或变量(转:)
struct sample_struct
{
char csName[16];
int iSeq;
int iType;
};
对于变量:
struct sample_strcut stTest;
一般情况下,清空stTest的方法:
stTest.csName[0]='/0';
stTest.iSeq=0;
stTest.iType=0;
用memset就非常方便:
memset(&stTest,0,sizeof(struct sample_struct));
如果是数组:
struct sample_struct TEST[10];
则
memset(TEST,0,sizeof(struct sample_struct)*10);
3, 参数问题:
#include <stdio.h>
#include <string.h>
int main()
{
char p[5];
p[3] = 'a';p[4]= 'b';
memset(p, '0' , 3);
printf("%s ,\n", p);
return 0;
}
运行结果:
看得出来,对于memset置0的时候,只对前三项初始化了,所以他们不影响后面两项,至于输出结果后面出现的(007f),则应该是对于上面这种把p的内存数限定的情况下,但是在结束的时候还没有找到退出的条件的,(即上面提到的几种情况)
char p[5] ;
printf("%s ,\n", p);多次运行结果如下:
strcpy:
头文件:#include <string.h>
char *strcpy(char *dest,char *src);把从src地址开始且含有NULL结束符的字符串赋值到以dest开始的地址空间,返回dest(地址中存储的为复制后的新值)。要求:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串
源文件:
char *strcpy(char *strDest, const char *strSrc);//strDest为目标,strSrc为源
{
assert((strDest!=NULL) && (strSrc !=NULL)); //如果两个为空则不用复制,直接中止
char *address = strDest; //用address指向strDest开始地址
while( (*strDest++ = * strSrc++) != ‘\0’ ) //复制,直到源串结束;
NULL ; //空操作
return address ; //返回strDest开始地址
}
}如:
char a[50], b[100];
strcpy(a, b,)这里将b的内容赋值给a,如果b中的(‘\0’)出现在前50个里面,那么就没有问题,如果在50个以后,那么就会造成内存泄露
这里,提一下:memcpy和strcpy的区别(转自:http://www.cnblogs.com/stoneJin/archive/2011/09/16/2179248.html)
strcpy和memcpy都是标准C库函数,它们有下面的特点。
strcpy提供了字符串的复制。即strcpy只用于字符串复制,并且它不仅复制字符串内容之外,还会复制字符串的结束符。
已知strcpy函数的原型是:char* strcpy(char* dest, const char* src);
memcpy提供了一般内存的复制。即memcpy对于需要复制的内容没有限制,因此用途更广。
void *memcpy(void *memTo, const void *memFrom, size_t size)
{
if((memTo == NULL) || (memFrom == NULL)) //memTo和memFrom必须有效
return NULL;
char *tempFrom = (char *)memFrom; //保存memFrom首地址
char *tempTo = (char *)memTo; //保存memTo首地址
while(size -- > 0 && *tempFrom++!='\0') //循环size次,复制memFrom的值到memTo中
*tempTo++ = *tempFrom++ ;
return memTo;
}
strcpy和memcpy主要有以下3方面的区别。
1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy
程序4:
#include <stdio.h>
#include <string.h>
int main()
{
char a[5]= "1234";
char b[5]= "abcd";
b[3]= '\0';
strcpy(a, b);
printf("%s\n", a);
memcpy(a, b, 5);
printf("%s\n", a);
return 0;
}
运行结果:
abc
abc
可以看出:两者的赋值都是碰到('\0')就退出
相关文章推荐
- ubuntu 安装texlive2013 支持中文
- HDU 4617 Weapon(计算几何、三维直线距离)
- JavaClientVM与JavaServerVM区别
- HDU 4616 Game(树形dp)
- 18个创业公司的18个方向,B2B创业成主流
- to write ...
- 6.16编程练习
- Tomcat中对Context应用
- XML总结. <DTD定义初级>
- HDU 4614 Vases and Flowers(线段树、二分)
- 异步处理的深入研究 二
- Studio报错 You need to use a Theme.AppCompat theme的两种解决办法
- SQL 查询数据后行数据合并为列
- 正则表达式个人总结.(中级)
- 《Unity_API解析》 第五章 Mathf类
- 第四届_黄金连分数
- logback配置详解
- HDU 4612 Warm up(边双连通、树的直径)
- HDU 1106 排序
- 第四届_39级阶梯