public class Demo { public static void main(String[] args) { int[] array = new int[]{1, 2, 3}; Demo demo = new Demo(); demo.printArray(array); } /** * 打印数组 * @param array */ public void printArray(int[] array){ System.out.println("第一种方法: "); for(int i : array){ System.out.print(i + ", "); } System.out.println(); System.out.println("第二种方法: "); // 这个也行 for(int i = 0; i < array.length; i++){ System.out.print(i + ", "); } } }
strcpy提供了字符串的复制。即strcpy只用于字符串复制,并且它不仅复制字符串内容之外,还会复制字符串的结束符。
memcpy提供了一般内存的复制。即memcpy对于需要复制的内容没有限制,因此用途更广。1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy
memcpy 和 memmove 都是C语言中的库函数:
1相同点:其原型相似,它们都是从src所指向的内存中复制count个字节到dest所指内存中。并返回dest的值。
2不同点:当源内存区域 和 目标内存区域无交叉重叠时,两者的结果是一样的,但如果有交叉,memcpy是从src的起始部分开始复制,所以此时会发生错误,交叉部分的src内容就会被覆盖掉了。
而memmove则由于采用不同的复制机制,所以可以正确处理第二种情况。
{
char *dp = ( char *)dst;
char *sp = ( char *)src;
assert((src!= 0)&&(dst!= 0)&&(n> 0)); // not null
// 非重叠
// dp < sp
// dp > (sp+n)
if(sp>dp||(sp+n)<dp)
{
while(n--)
*(dp++) = *(sp++);
*dp = ' \0 ';
}
else if(sp<dp) // 重叠 (此时条件 sp<dp<(sp+n))如果sp==dp则快速的返回
{ // 反向拷贝
sp += n;
dp += n;
*dp = ' \0 ';
while(n--)
*(--dp) = *(--sp);
}
}
原型:extern void *memset(void *buffer, int c, int count);
用法:#include <string.h>
功能:把buffer所指内存区域的前count个字节设置成字符c。
说明:返回指向buffer的指针。用来对一段内存空间全部设置为某个字符。
举例:char a[100];memset(a, '\0', sizeof(a));
memset可以方便的清空一个结构类型的变量或数组。
但注意,类中有虚函数(即虚指针)构造函数中使用memset会情况vptr.
如:
struct sample_struct
{
char
int
int
};
对于变量
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
则
memset(TEST,0,sizeof(struct sample_struct)*10);
空指针(NULL,0),野指针,void*
//访问a的时候,实际上都是访问的0x1000单元中的10
现在定义:int *p;//给指针变量p分配一个内存单元,假设为0x1003;
//此时,0x1003中的值是不确定/随机的,p是野指针
//即野指针指向不可用内存区域的指针
p=&a;//在0x1003单元中保存0x1000(存放了变量a的内存地址)
p=NULL,就是说:内存单元0x1003不存放任何变量的内存地址。
void 指针。
int n=3, *p;
void *gp;
gp = &n;
p=(int *)gp1;
NULL指针相对野指针的好处:可以if判断是否为空;对NULL指针操作/删除不会发生不可预知的错误
空指针/0/NULL
空指针是一个被赋值为0的指针,在没有被具体初始化之前,其值为0.
NULL 是一个标准规定的宏定义,用来表示空指针常量。
#define NULL 0 或者
#define NULL ((void*)0)
判断一个指针是否为空指针:
f(!p) 和 if(p == NULL) ,if(NULL == p)
VOID指针
void *可以指向任何类型的数据。
任何指针都可以赋值给void指针。
void指针赋值给其他类型的指针时都要进行转换,如malloc 函数,其返回类型是 void* 类型。
int* p;
p = (int *) malloc (sizeof(int));
赋值前要进行强制转化。
按照ANSI(American National Standards Institute)标准,不能对void指针进行算法操作:
void * pvoid;
pvoid++; //ANSI:错误
pvoid += 1; //ANSI:错误
//ANSI标准之所以这样认定,是因为它坚持:进行算法操作的指针必须是确定知道其指向数据类型大小的。
//例如:
int *pint;
pint++; //ANSI:正确
GNU编译器认为正确:
pvoid++; //GNU:正确
pvoid += 1; //GNU:正确
void不能代表一个真实的变量
下面代码都企图让void代表一个真实的变量,因此都是错误的代码:
void a; //错误
function(void a); //错误
#define CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
int *p=(int*)malloc(sizeof(int));
*p=6;
cout<<*p<<endl;
free(p);
p=NULL;
_CrtDumpMemoryLeaks();//注意这条语句的摆放位置,因为这会直接影响到你的判断结果
return 0;
}