使用 @class来导入类。
应用场景: B类导入A类
A.h里 声明 @class
@class B;
A.m里 注入import
import "B.h"
[B b];
2015年8月26日星期三
2015年7月7日星期二
malloc的使用
char m;
scanf(" %c",&m); //前面加空格是为了去掉空格、回车等操作
NSLog(@"the character is %c",m);
上面这个程序是各位比较熟悉的两个方法一个输入、一个输出,但是如果我改一下改成
char *m;
NSLog(@"\n请输入一个字符");
scanf(" %c",m);
NSLog(@"\nthis is %c",*m);
是否正确呢,编译时是否会报错,运行时是否会出问题?
其实这个程序,如果编译的时候不会出现异常,但是如果运行的话,会出现运行时异常(出现lldb命令,使用kill命令结束即可),原因是就是我们定义了一个char指针m,这个指针没有进行初始化赋值,导致程序运行时无法找到存储这个字符的内存空间,如果改成
char *m;
m=(char *)malloc(sizeof(char));//malloc()动态分配内存,用malloc分配内存的首地址,然后赋值给m
NSLog(@"\n请输入一个字符");
scanf(" %c",m);
NSLog(@"\nthis is %c",*m);
趁热再来一发,因为使用malloc进行动态分配空间,所以我们可以使用char指针输出字符串,如下:
char *a;
a=(char *)malloc(sizeof(char)*100); //动态分配100个连续的char内存地址
NSLog(@"\n请输入一个字符串");
scanf(" %s",a);
NSLog(@"\nthis is %s",a);
C语言memset函数详解与误用
memset为内存填充函数,包含在<string.h>头文件中,可以用它对一片内存空间进行初始化,其原型为
void *memset(void *s, int v, size_t n);
英文释义如下:
Copies the value v (converted to type unsigned char) to the first n bytes pointed to by s; returns s.
这里s可以是数组名,也可以是指向某一内在空间的指针;v为要填充的值;n为要填充的字节数,通常为sizeof(s);
void *memset(void *s, int v, size_t n);
英文释义如下:
Copies the value v (converted to type unsigned char) to the first n bytes pointed to by s; returns s.
这里s可以是数组名,也可以是指向某一内在空间的指针;v为要填充的值;n为要填充的字节数,通常为sizeof(s);
使用memset时要注意的是,memset是逐字节进行填充,所以s一般为char *型。
对于其它类型的s,可以填充的值有两个,0和-1。这是因为计算机中用二进制补码表示数字,0的二进制补码为全0,-1的二进制补码为全1。如果要初始化为其它的值,可以用一个for循环,如下:
for (int i=0; i<n; i++)
{
s[i] = v;
}
memset() 函数常用于内存空间初始化。如:
char str[100];
memset(str,0,100);
char str[100];
memset(str,0,100);
memset可以方便的清空一个结构类型的变量或数组。
如:
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);
对于赋特定的值,需注意
char a[5];
memset(a,1,5); //成功赋值为0x01
memset(a,1,5); //成功赋值为0x01
int a[5];
memset(a,1,5);//这里改成memset(a,1,5 *sizeof(int))也是不可以的
memset(a,1,5);//这里改成memset(a,1,5 *sizeof(int))也是不可以的
因为第一个程序的数组a是字符型的,字符型占据内存大小是1Byte,而memset函数也是以字节为单位进行赋值的。
而第二个程序a是整型的,使用memset还是按字节赋值,这样赋值完以后,每个数组元素的值实际上是0x01010101即十进制的16843009。
而第二个程序a是整型的,使用memset还是按字节赋值,这样赋值完以后,每个数组元素的值实际上是0x01010101即十进制的16843009。
memset,memcpy,strcpy 的区别
一.函数原型
strcpy
extern char *strcpy(char *dest,char *src);
#include <string.h>
功能:把src所指由NULL结束的字符串复制到dest所指的数组中
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
返回指向dest的指针
memcpy
extern void *memcpy(void *dest,void *src,unsigned int count);
#include <string.h>
功能:由src所指内存区域复制count个字符串到dest所指内存区域.
说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针.
memset
extern void *memset(void *buffer,int c,int count);
#include <string.h>
功能:把buffer所指内存区域的前count个字节设置成字符c
说明:返回指向buffer的指针.
二.区别
memset 用来对一段内存空间全部设置为某个字符,一般用于在对定义的字符串初始化为' '或者'\0';
例: char a[100];
memset(a,'\0',sizeof(a));
memcpy 是用来做内存拷贝,可以用来拷贝任何数据类型的对象,可以指定拷贝的数据长度;
例:
char a[100],b[50];
memcpy(b,a,sizeof(b)); //注意:如果使用sizeof(a),会造成内存溢出
mem是一段内存,他的长度,必须自己记住.memcpy是见着什么拷贝什么。
strcpy 就只能拷贝字符串,它遇到'\0'就结束拷贝;
例:char a[100],b[50];
strcpy(a,b);
如用strcpy(b,a)要注意a中的字符串长度(第一个'\0'之前) 是否超过50,如果超过,则会造成b的
内存溢出.它是不会拷贝'\0'的,所以一般还有加一个语句:
*a='\0';
三.使用技巧
memset 可以方便的清空一个数据结构的变量或数组.
如:
struct sample_struct
{
char csName[16];
int iSeq;
int iType;
};
对于变量
struct sample_struct stTest;
一般情况下,初始化stTest的方法:
stTest.csName[0]='\0';
stTest.iSeq=0;
stTest.iType=0;
而用memset:
memset(&stTest,0,sizeof(struct sample_struct));
如果是数组:
struct sample_struct TEST[100];
memset(TEST,0,sizeof(struct sample_struct)*100);
strcpy是拷贝字符串,以\0为标志结束(即一旦遇到数据值为0的内存地址拷贝过程即停止)
strcpy的原型为
char *strcpy(char *dest, const char *src)
而memcpy是给定来源和目标后,拷贝指定大小n的内存数据,而不管拷贝的内容是什么(不仅限于字符)
memcpy的原型为
void *memcpy(void *dest, const void *src, size_t n);
一.函数原型
strcpy
extern char *strcpy(char *dest,char *src);
#include <string.h>
功能:把src所指由NULL结束的字符串复制到dest所指的数组中
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
返回指向dest的指针
memcpy
extern void *memcpy(void *dest,void *src,unsigned int count);
#include <string.h>
功能:由src所指内存区域复制count个字符串到dest所指内存区域.
说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针.
memset
extern void *memset(void *buffer,int c,int count);
#include <string.h>
功能:把buffer所指内存区域的前count个字节设置成字符c
说明:返回指向buffer的指针.
二.区别
memset 用来对一段内存空间全部设置为某个字符,一般用于在对定义的字符串初始化为' '或者'\0';
例: char a[100];
memset(a,'\0',sizeof(a));
memcpy 是用来做内存拷贝,可以用来拷贝任何数据类型的对象,可以指定拷贝的数据长度;
例:
char a[100],b[50];
memcpy(b,a,sizeof(b)); //注意:如果使用sizeof(a),会造成内存溢出
mem是一段内存,他的长度,必须自己记住.memcpy是见着什么拷贝什么。
strcpy 就只能拷贝字符串,它遇到'\0'就结束拷贝;
例:char a[100],b[50];
strcpy(a,b);
如用strcpy(b,a)要注意a中的字符串长度(第一个'\0'之前) 是否超过50,如果超过,则会造成b的
内存溢出.它是不会拷贝'\0'的,所以一般还有加一个语句:
*a='\0';
三.使用技巧
memset 可以方便的清空一个数据结构的变量或数组.
如:
struct sample_struct
{
char csName[16];
int iSeq;
int iType;
};
对于变量
struct sample_struct stTest;
一般情况下,初始化stTest的方法:
stTest.csName[0]='\0';
stTest.iSeq=0;
stTest.iType=0;
而用memset:
memset(&stTest,0,sizeof(struct sample_struct));
如果是数组:
struct sample_struct TEST[100];
memset(TEST,0,sizeof(struct sample_struct)*100);
strcpy是拷贝字符串,以\0为标志结束(即一旦遇到数据值为0的内存地址拷贝过程即停止)
strcpy的原型为
char *strcpy(char *dest, const char *src)
而memcpy是给定来源和目标后,拷贝指定大小n的内存数据,而不管拷贝的内容是什么(不仅限于字符)
memcpy的原型为
void *memcpy(void *dest, const void *src, size_t n);
2015年6月24日星期三
protocol 协议使用
protocl 协议跟java的接口差不多的概念
首先要定义
@protocol PainterSetupViewDelegate;
这是定义接口
@protocol PainterSetupViewDelegate<NSObject>
- (void)painterSetupViewController:(PainterSetupViewController *)
controller setColor:(UIColor *)color;
- (void)painterSetupViewController:(PainterSetupViewController *)
controller setWidth:(float)width;
@end
使用他的时候
.h里定义他
@interface ViewController : UIViewController<PainterSetupViewDelegate>
{
}
@end
.m里就得实例化他了
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(IBAction)PenClick // Pen Type
{
[(MainPainterView *)self.view setpCurType:PEN];
}
-(IBAction)LineClick // Line Type
{
[(MainPainterView *)self.view setpCurType:LINE];
}
-(IBAction)CircleClick // Circle Type
{
[(MainPainterView *)self.view setpCurType:CIRCLE];
}
-(IBAction)EraseClick // Erase Type
{
[(MainPainterView *)self.view setpCurType:ERASE];
}
-(IBAction)RectangleClick // Taegeuk Type
{
[(MainPainterView *)self.view setpCurType:RECTANGLE];
}
-(IBAction)SetupClick
{
if (pPainterSetupViewController == nil) {
PainterSetupViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:@"PainterSetupViewController"];
viewController.delegate = self;
pPainterSetupViewController = viewController;
}
[self presentViewController:pPainterSetupViewController animated:YES completion:nil];
}
- (void)painterSetupViewController:(PainterSetupViewController *) controller setColor:(UIColor *)color
{
[(MainPainterView *) self.view setpCurColor:color];
}
- (void)painterSetupViewController:(PainterSetupViewController *) controller setWidth:(float)width
{
[(MainPainterView *) self.view setpCurWidth:width];
}
@end
2015年4月20日星期一
2015年3月28日星期六
2015年3月26日星期四
객체 생성하기(alloc,release)
alloc와 release는 묶어서 나타나야 한다.
alloc는 메모리를 할당하는 것이고 release는 반납하겠다는 뜻이다.
예문
sample =[[MySample alloc] init];
[sample release];
alloc는 메모리를 할당하는 것이고 release는 반납하겠다는 뜻이다.
예문
sample =[[MySample alloc] init];
[sample release];
@synthesize와@property
이두가지로 선언했다면 해당 메서드를 자동으로 생성하도록 하는 지시어다.
@synthesize 는 get와set를 생략한다
@dynamic은 부모클래스에서 @synthesize된 getter와 setter를 사용하겠다고 선언
Xcode 4.4부터 .h가 property가 선언되었다면 .m에서 @synthesize를 사용하지 않아도
"_"만 붙으면 해당 synthesize world=_world와 같은 효과이다.
@synthesize 는 get와set를 생략한다
@dynamic은 부모클래스에서 @synthesize된 getter와 setter를 사용하겠다고 선언
Xcode 4.4부터 .h가 property가 선언되었다면 .m에서 @synthesize를 사용하지 않아도
"_"만 붙으면 해당 synthesize world=_world와 같은 효과이다.
property的 strong以及weak
property의 strong과 weak는 ARC(XCode 5)가 도입되면서 추간된거다
strong:은 새로운 객체를 도입하면 해당 객체는 무조건 ratain된다.즉 해당객체를 사용하지 않으면
메모리가 자동 해제된다 .
weak: 해당객체가 메모리에서 해제될 때 자동으로 nil값을 대입해 준다
下面的描述写的比较明白。
并定义
再来猜一下,下面输出是什么?
结果是:String 2 = null
strong:은 새로운 객체를 도입하면 해당 객체는 무조건 ratain된다.즉 해당객체를 사용하지 않으면
메모리가 자동 해제된다 .
weak: 해당객체가 메모리에서 해제될 때 자동으로 nil값을 대입해 준다
下面的描述写的比较明白。
property 中的strong 与weak
strong关键字与retain关似,用了它,引用计数自动+1,用实例更能说明一切
@property (nonatomic, strong) NSString *string1;
@property (nonatomic, strong) NSString *string2;
有这样两个属性,
@synthesize string1;
@synthesize string2;
猜一下下面代码将输出什么结果?
self.string1 = @"String 1";
self.string2 = self.string1;
self.string1 = nil;
NSLog(@"String 2 = %@", self.string2);
结果是:String 2 = String 1
由于string2是strong定义的属性,所以引用计数+1,使得它们所指向的值都是@"String 1", 如果你对retain熟悉的话,这理解并不难。
由于string2是strong定义的属性,所以引用计数+1,使得它们所指向的值都是@"String 1", 如果你对retain熟悉的话,这理解并不难。
接着我们来看weak关键字:
如果这样声明两个属性:
@property (nonatomic, strong) NSString *string1;
@property (nonatomic, weak) NSString *string2;
并定义
@synthesize string1;
@synthesize string2;
再来猜一下,下面输出是什么?
self.string1 = @"String 1";
self.string2 = self.string1;
self.string1 = nil;
NSLog(@"String 2 = %@", self.string2);
结果是:String 2 = null
分析一下,由于self.string1与self.string2指向同一地址,且string2没有retain内存地址,而self.string1=nil释放了内存,所以string1为nil。声明为weak的指针,指针指向的地址一旦被释放,这些指针都将被赋值为nil。这样的好处能有效的防止野指针。在c/c++开发过程中,为何大牛都说指针的空间释放了后,都要将指针赋为NULL. 在这儿用weak关键字帮我们做了这一步。
订阅:
博文 (Atom)