#define Number 10
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
//指针[通过%p可以把地址打印出来] 内存地址
// int a = 20;
// int b = 30;
// int *p = &a;
//
// int *z = &b;//取地址符 *此时仅仅起到标识作用,告诉编译器,P事一个存放地址的变量
//使用&可以取到变量a在内存中的首地址
// printf("%p\n",&a);//%p 用来输出地址(十六进制)
// printf("%p",&b);
// int a = 10;
// int b = 20;
// //指针变量,专门用于储存地址的变量
// //定义一个指针变量,并赋初始值NULL
// //NULL == 0x0(十六进制的零)
// int * p = NULL;
// printf("%p",p);
// //把a的地址赋值给指针变量p,通过p可以找到a的储存单元
// p = &b;
// //通过地址间接访问内存单元里面的数据
// *p = 15;
// printf("%p",*p);
// int a = 5;
// //此时的*代表定义一个指针变量
// int * p = &a;
// a = 8;
// //此时的*代表使用地址间接访问内存单元里面的数据
// //两个*出现的位置不一样,含义就不一样
// //区别:前面是否有类型修饰符
// printf("%p",*p);
// int a = 8,b = 3;
// int * p = &a;
// int *q = &b;
// *p = 4;
// a = 6;
// b = 5;
// *q = 10;
// printf("%d %d", *p, *q);
// int a = 8, b = 9;
// int * m = &a;
// int * n = &b;
// //指针的重新赋值,意味着指针的重指向
// m = n;
// printf("%d %d", *m, *n);
// int a = 4, b = 6, c = 9;
// int * x = &b;
// int * y = x;
// int * z = &a;
// *x = 10;
// y = z;
// *z = 7;
// z = &c;
// printf("%d %d %d", *x, *y, *z);
//使用指针,必须有明确的指向,否则很危险
// int * p;//没有申请内存空间
// *p = 5;
// printf("%d",*p);
//内存单元地址偏低的一段储存空间操作系统在使用,不允许访问
// int * p = NULL;
// *p = 6;
// printf("%d", *p);
//32位系统指针是4个字节,64位系统指针是8个字节
//指针变量所占内存空间的大小跟指针类型没有关系
//取决于操作系统的位数
//32位操作系统一个指针变量占4个字节
//64位操作系统一个指针变量占8个字节
// int a = 10;
// char * p = &a;
// printf("%lu",sizeof(p));//sizeof(char *);
//数组名,是数组这段连续储存空间的首地址
// int array[5] = {2,3,6,4,5};
// printf("%p\n", array);
// printf("%p\n",&array[0]);
// printf("%p\n",&array[1]);
// printf("%p\n",&array[5]);
// int * p =array;
//指针运算,指针每次加1加的字节数跟指针的类型有关int *指针是加一个4字节,char *指针是加1字节
//p + 1 是相当于p的地址加4个字节之后的新地址,原本的p没有动
//p++等价于p = p + 1,相对于p的地址加4个字节的新地址重新给p赋值,p的指向改变
// printf("%d\n",*p);
// printf("%d\n",*(p + 1));
// int * p =array;
// *(p + 2) = 4;
// *p = 3;
// p++;
// *(p + 1) = 5;
// printf("%d %d %d\n",array[0],array[1],array[2]);
// int array[3] = {2,3,6};
// int * p = array;
// //以下四种写法完全等价
// printf("%d",array[1]);
// printf("%d",p[1]);
// printf("%d",*(array + 1));
// printf("%d",*(p + 1));
//
//数组名是一个常量地址,不允许重新赋值(不能重指向)
// int a = 1;
// int array[4] = {2,5,4,6};
// //array = &a;//error
// int * p = array;
// p = &a;
// printf("%d",*p);
// int array[10] = {0};
// int * p = array;
// for (int i = 0; i < 10; i++) {
//// *(p + i) = arc4random() % 101;
//// printf("%d\t", *(p + i));
// *p = arc4random() % 101;
// printf("%d\t",*p);
// p++;
// }
// p = array;
// printf("%d",*p);
//
// int array[Number] = {0};
// int * p = array;
// for (int i = 0; i < Number; i++) {
// *(p + i) = arc4random() % 101;
// printf("%d\t",*(p + i));
// }
// //冒泡排序 -- 优化
// BOOL needNext = YES;
// for (int i = 0; i < Number - 1 && needNext; i++) {
//
// needNext = NO;
// for (int j = 0; j < Number - 1 - i; j++) {
// if (*(p + j) > *(p + j + 1)) {
// needNext = YES;
// int tem = *(p + j);
// *(p + j) = *(p + j + 1);
// *(p + j + 1) = tem;
// }
// }
//
// }
// printf("\n");
// for (int i = 0; i < Number; i++) {
// printf("%d\t",*(p + i));
// }
// for (int i = 0; i < Number - 1; i++){
// int min = i;
// for (int j = i + 1; j < Number; j++) {
// if (*(p + min) < *(p + j)) {
// min = j;
// }
// }if (min != i) {
// int tem = *(p + min);
// *(p + min) = *(p + i);
// *(p + i) = tem;
// }
//
// }
// printf("\n");
// for (int i = 0; i < Number; i++) {
// printf("%d\t",*(p + i));
// }
//不同类型的指针区别
//1.指针在做运算的时候,每次加一移动的字节数不一样
//2.通过指针的使用*来取值的时候,每次取的字节数不一样
// short array[4] = {1,6,3,8};
// int * p = (int *)array;//强制类型转换
// printf("%d",*p);
//数组名和一个指向数组首地址的指针变量的异同点:
//相同点:
//不同点:
//1.使用sizeof测算的时候,编译器会自动检查如果传入的时一个数组名,则返回的时真个数组所占用的全部的内存空间,如果传入的是一恶搞指针变量,则返回的是指针变量所占的内存空间
//2.数组名是常量地址,不可以重新指向,指向数组首地址的指针变量是一个变量,允许重新赋值,重指向
// int array[] = {1,2,3,4,5};
// int * p =array;
// printf("%lu\n",sizeof(array));
// printf("%lu\n",sizeof(p));
// char str[10] = "iphone";
// //%s工作原理,从给定的地址开始输出到\0结束
// char * p = str;
// *p++ = ‘A‘;
// printf("%s\n",str);
// printf("%s\n",p); //%s工作原理,从给定的地址开始输出到\0结束
// char str[] = "I want an iphone6";
// *(str + 1) = ‘\0‘;
// printf("%s\n",str);
// *(str + 6) = ‘\0‘;
// printf("%s\n",str + 2);
// *(str + 9) = ‘\0‘;
// printf("%s\n",str + 7);
// printf("%s\n",str + 10);
//两种形式定义字符串
//这种形式定义的字符串,是把常量区的iPhone ,拷贝到栈区
//数组名是常量地址,不能重新指向
//但是数组里的内容在栈区存储,可以修改
// char str[10] = "iPhone";
// printf("%s\n",str);
// char * string = "iPhone";
// printf("%s\n",string);
//这种形式定义的字符串是把常量区的字符串地址直接赋值给一个指针变量,字符串中的内容不可以改变,因为在常量去存储
//但是指针是一个变量,可以重新指向.
// char str[10] = "iPhone";
// strcmp(str, "Android");
// printf("%s\n",str);
// char * string = "iPhone";
// string = "Android";
// printf("%s\n",string);
// (1)
// char str[] = "ssd dfdfads asdf sadf sdaf asdf asdf";
// char * p = str;
// int count = 0;
// while (*p != ‘\0‘) {
// if (*p == ‘ ‘){
// count++;
// }
// p++;
// }printf("%d",count);
// (2)
// char str[] = "ssd dfdfads asdf sadf sdaf asdf asdf";
// char * p = str;
// int count = 0;
// int i = 0;
// while (*(p + i) != ‘\0‘) {
// if (*(p + i) == ‘ ‘) {
// count++;
// }i++;
// }
// printf("%d",count);
return 0;
}