基本的c和c++编程
创新互联公司是一家专业提供广饶企业网站建设,专注与成都做网站、成都网站制作、html5、小程序制作等业务。10年已为广饶众多企业、政府机构等服务。创新互联专业网络公司优惠进行中。
我将会引导你学习一些简单的c/c++课程,让你对它有一个基本的了解。Objective-C和c/c++有很多共同点,所以在本章你不需要学习很多新的概念。理解c/c++同样能够帮助你更好的编写Objective-C,因为Objective-C是C的一个超集。
c编程
c++同样是c的超集,所以你必须先学会如何使用c,然后在接下来的部分学习c++。我只会讨论使用c编程和iPhone编程不同的那部分。
基本数据类型和函数
c的数据类型很少:integer,floating point,double precision floating point 和characters。在不同的操作系统中,每一种数据类型的二进制位是不同的,甚至在iOS的不同版本中也不同。下面的是每种数据类型的取值范围,但是你不应该太过依赖于这些信息,尤其是在做重要决定的时候:
char:-128到127
integer:-32768到+32767
float:3.4 e-38 到 3.4 e+38
double:1.7 e -308 到 1.7 e +308
还有很多修饰符可以应用带这些基本类型上;例如,short和long可以用在integer上。
short int sh;
long int counterLong;
使用这些修饰符的目的是为integer提供一个更小或更大的范围;例如,short是16位,long是32位。iOS编译器能确保short不比int长,long不比int短。
你也可以使用signed和unsigned修饰符。如果你没有指定任何signed或unsigned,编译器默认使用signed。使用unsigned修饰符,能让数据范围扩大一倍。例如,integer的范围从0到65535.
通常你只需使用integer。如果你想存储一个很大的integer,就添加long修饰符。使用short覆盖int,内存优化非常小,你基本上可以忽略它。
注意:如果你使用Objective-C,你应该使用NSInteger,NSUInteger,和CGFloat。这些是苹果内置的包装类,它们封装了底层的实际数据结构。 |
c没有Boolean数据类型,但是Objective-C有。在c中,如果一个Boolean语句返回true,值是1;否则是0.例如 2==2将返回1,而 2==3将返回0。为了增强代码的可读性,你可能需要定义两个Boolean宏,类似这样:
#define TRUE 1
#define FALSE 0
int t = (1 == 1);
if (t == TRUE) {
// do your work here
}
尽管c函数和Objective-C函数看起来不同,但是你依然需要返回一个值和接收参数。下面是两个c函数的例子:
int pi_value() {
return 3.14;
}
int add_number(int n1, int n2) {
return n1 + n2;
}
指针
指针在c编程中是非常重要的。在Objective-C中,你通常会看到Objective-C有同样的指针概念和语法,例如NSMutableArray *myArray = [NSMUtableArray array]。但是,你不需要知道底层内存的细节,因为在Objective-C中指针可以很简单的认为它是一个对象。但是,如果使用c,你要做的事情将更多,c中指针的概念也更加复杂。
内存指针概念
主存可以看做是一个cell的数组,每一个cell看做是一个字节,每一个数据item存储在cells的group中。一个char存储在一个cell,一个integer存储在两个cell中,而一个long存储在4个cell中。每一个cell都可以被数字化,因此每一个变量将有一个内存地址来存储数据。
图 9-1 内存指针概念
指针是一个变量,它保存了另一个变量的内存地址。例如,图9-1变量p里面的数据保存了变量c的内存地址。所以我们说,p指向了c,你可以用语句 p = &c 来表示它;&操作符返回变量c的内存地址,然后赋值给p。&只能应用在内存中的变量,数组和对象,不能用在表达式或常量上。指针的另一个操作符是*;当它应用到指针,指针操作符然后给定地址内存中的内容。这个过程通常称为解引用。这边有一个源代码显示了是如何进行工作的:
int x = 1, y = 2, a[3];
int *ip; // ip is a pointer that can only point to integer
ip = &x; // ip now points to x
y = *ip; // y is now 1, because you return the data pointed by ip*ip = 0; // x is now 0, I set the data pointed by p to be 0
ip = &a[0]; // ip now points to the first element of array a
值传递和引用传递
在c编程中,你参数传递有两种方式:值传递和引用传递。通过值传递把参数传递给函数是通常的方式。
int add(int t1, int t2) {
return t1 + t2;
}
然而,值传递是不起作用的,如果你想要交换两个变量的值:
void swap(int x, int y) {
int temp;
temp = x;
x = y;
y = temp;
}
int main() {
int x = 3, y = 4;
swap (x, y);
}
问题是在函数返回后,里面的两个变量值并没有交换。当swap方法被调用的时候,x和y的值会被拷贝然后再传递给函数swap(3, 4)。因此,原始的变量值并没有改变。
如果你想要改变存储在变量x和y的内部值,你需要使用引用传递。通过引用传递,x和y的内存地址被传递进来。使用x和y的内存地址,你能够非常简单的修改存储在她们内存的值了。
void swap(int *px, int *py) {
int temp;
temp = *px; // temporarily store the value inside the memory of x
*px = *py; // set the value inside the memory of x.
*py = temp; // set the value inside the memory of y.
}
int main() {
int x = 3, y = 4;
swap (&x, &y);
}
图 9-2 能够让你更好的理解这个过程。
高级数据类型
在c中还有一些高级数据类型:array(数组),string(字符串)和struct(结构体)。这些在Objective-C中都是支持的,但是你应该谨慎的使用,因为会使得代码难以理解,后续维护也变得更加困难。所有这些数据结构在Objective-C中都有对应的包装类,使得代码更加面向对象。但是,在很多情况下,你仍然需要使用c数据结构来提升性能或处理来自c/c++库的调用结果。
Array数组
在Objective-C中,你通常会使用NSArray或NSMutableArray对象来表示一个数组。但是,在c中,你没有这些概念,因此你应该集中在数组的基本概念上。在c中为了定义一个数组,你需要提前知道数组的长度,类似这样的定义:
int a [10]; // an array with maximum ten elements
a[0], a[1], a[2] ... a[9]is the first, second ... tenth elements of the array
指针和数组有非常密切的关系。
int *pa;
pa = &a[0];
这个指针赋值代码将pa指向数组的第一个元素。根据指针那部分解释的,赋值语句 x = *pa,x包含了a[0]的值。
你可以通过简单的算术运算来移动指针指向数组内的不同元素,pa+1会返回下一个元素的地址,pa-1返回上一个元素的地址。图9-3展示了指针在数组内部的算术运算。
这些计算并不依赖于数组内存变量的类似或大小。因此,(pa + i)将返回数组中的第i个元素的地址。另一个在数组和指针之间非常重要的关系是你可以使用 *(aa + i)来引用a[i]。
在数组和指针之间有一个不同点:指针是一个变量,所以pa = a和pa++都是合法的。然而,a = pa和a++是不合法的。
String字符串
在c中字符串常量,例如 "I am Khang",一个以'\0'结尾的字符数组,这样程序就能够找到数组的结束部分。因为string是一个字符数组,你可以简单的将它赋值给指针。
char *pmessage;
pmessage = "I am Khang";
你可以把string看做是一个正常的数组或指针那样进行操作,如下面的源代码:
void my_string_copy (char *s, char *t) {
while (*s++ = *t++) ;
}
my_string_copy函数是非常简单的;它有两个字符指针,将string t(通过字符指针来表示)中的字符元素赋值给赋值给string s。
注意:当你把数组作为一个参数传递给函数时,c会自动的将它转换为指向数组的指针。 |
这里有另一个例子,使用了字符数组,但是并没有使用指针,它展示了数组和指针的内部转换:
int my_string_length(char *s) {
int i = 0;
while (s[i] != '\0') {
i++;
}
return i;
}