//指针的定义:本质是一个变量,只不过此变量是用来存储地址的
//地址:内存单元的编号,只是一个编号而已,是一个0x开头的 16 进制数
//定义一个整型指针
int a = 10;
int *p = NULL;//NULL恒等于零
p = &a; //将变量a的地址赋值给指针变量a
printf("&a = %p\n",&a);
printf("p = %p\n",p);
// 直接访问a变量的值
printf("a = %d\n",a);
// 间接访问a变量的值,此时*p ( * + 变量名称)是取值操作,取来的变量p存储的地址对应的内存空间
//p --- 取址 *p --- 取值
printf("*p = %d\n",*p);
a = 20;
printf("a = %d\n",a);
printf("*p = %d\n",*p);
// *p = 赋值操作 为*p所对应的内存里面的值赋值
*p = 34; //先通过p找到地址,然后在*p地址里赋值
printf("a = %d\n",a);
printf("*p = %d\n",*p);
//定义一个整型变量,初始值为30,通过指针变量为其赋值和取值
int b = 30;
int *bp = NULL;
bp = &b;
*bp = 60;
printf("*p = %d\n",*bp);
//定义三个整型变量,定义一个指针变量指向第二个变量
int y = 2,z = 3;
int *p2 = NULL;
p2 = &y;//把y的地址赋值给p2
*p2 = 4;//给p2所在的内存空间重新赋值为4,即把值赋给y
printf("y = %d\n",y);
p2 = &z;//重新把z的地址赋值给p2,此时p2指针重新指向一个新的地址&z
*p2 = 6;//给p2指向的内存空间重新赋值为6
printf("z = %d\n",z);
//定义两个整型变量,初始值为30 50,
int n1 = 30,n2 = 50;
int *pn1 = &n1;
int *pn2 = &n2;
//第一种方法
int temp = *pn1;
*pn1 = *pn2;
*pn2 = temp;
printf("n1 = %d,n2 = %d\n",*pn1,*pn2);
//第二种方法
int *tempP = pn1;
pn1 = pn2;
pn2 = tempP;
printf("n1 = %d,n2 = %d",n1,n2);
//指针的算术运算
int a = 12,b = 15,c = 18;
//定义一个整型指针
int *p = &b;
printf("*p = %d\n",*p);
printf("b = %d\n",b);
printf("*(p + 1) = %d\n",*(p + 1));
printf("a = %d\n",a);
printf("*(p - 1) = %d\n",*(p - 1));
printf("c = %d\n",c);
//p + 1 加一个单位意味着加4个字节(加几个字节取决于这个指针变量类型所占的字节数),因为此时a的地址比b的地址高,所以加4个字节,也就是此时指针指向的时a的地址,然后通过(*地址)取值
//p++ //向高位移动一个地址 n个字节
//p-- //向低位移动一个地址 n个字节
//数组与指针的关系
int array[5] = {1,2,3,4,5};
int *pArr = array;//因为数组的首地址就是该数组的数组名,所以直接把数组名给指针变量pArr
//如何求数组array第一个元素的值
printf("array[0] = %d\n",array[0]);
//首地址为数组名,所以 *数组名|*指针变量名所取得的都是数组的第一个元素的值
printf("*pArr = %d\n",*pArr);
printf("*array = %d\n",*array);
//取数组中第三个元素的值
printf("*(pArr + 2) = %d\n",*(pArr + 2));
//重新赋值
*(pArr + 2) = 8;
printf("*(pArr + 2) = %d\n",*(pArr + 2));
//取第二个元素的几种方法
printf("array[1] = %d\n",array[1]);
printf("1[array] = %d\n",1[array]);
//下面这两种是最常用的
printf("*(pArr + 1) = %d\n",*(pArr + 1));
printf("*(array + 1) = %d\n",*(array + 1));
printf("*(&array[0] + 1) = %d\n",*(&array[0] + 1));
printf("pArr[1] = %d\n",pArr[1]);
printf("1[pArr] = %d\n",1[pArr]);
//输出数组array的所有的值
printf("array数组里的所有的元素分别为:");
for (int i = 0; i < 5; i++) {
printf("%d ",*(pArr + i));
}
//定义一个有十个元素的整型数组,定义指针变量存储数组首地址,通过指针完成元素的随机赋值[20 40],然后升序排列
int arr[10] = {0};
int *parr = arr;
printf("数组的元素为:");
for (int i = 0; i < 10; i++) {
*(parr + i) = arc4random() % 21 + 20;
printf("%d ",*(parr + i));
}
printf("\n升序完成之后的数组的元素分别为:");
for (int i = 0; i < 10 - 1; i++) {
for (int j = 0 ; j < 10 - 1 - i; j++) {
if (*(parr + j) > *(parr + j + 1)) {
int temp = *(parr + j);
*(parr + j) = *(parr + j + 1);
*(parr + j + 1) = temp;
}
}
}
for (int i = 0; i < 10; i++) {
printf("%d ",*(parr + i));
}
//指针和字符串
char Symbol[] = "Tonight i will close to you!";
char *pSymbol = Symbol;//把数组名也就是首地址赋值给指针变量pSymbol
long charStrlen = strlen(Symbol);
for (int i = 0; i < charStrlen; i++) {
printf("%c ",*(pSymbol + i));
}
//%s 的工作原理就是从我们给定的地址开始输出字符,遇到\0结束
printf("\n%s",Symbol);//首地址
printf("\n%s",Symbol + 8);//首地址往上(高地址)平移8个单位
printf("\n%s",Symbol + 2);
//输出其中某一段字符
*(pSymbol + 20) = '\0';//找到首地址往上平移20个单位的位置,然后将其值修改为'\0'
printf("\n%s",Symbol + 10);
//将所有的空格改为* 'o'换成'O'
char changechar[] = "You Can You Up,No Can No BB!";
char *pFunny = changechar;//将字符串的名称赋值给我们的字符指针变量.因为字符串的名字就是首地址
int i = 0;
//取到'\0'是则结束循环 *地址就是取值
while (*(pFunny + i) != '\0') {
//取到空格,则是使用 *p 取值,然后重新赋值
if (*(pFunny + i) == ' ') {
*(pFunny + i) = '*';
}
if (*(pFunny + i) == 'o') {
*(pFunny + i) = 'O';
}
i++;
}
printf("\n%s",changechar);
return 0;
}
//总结
指针和数组的关系
1.数组所占的空间大小:元素个数 * 每个元素所占的内存大小(字节数)
2.指针所占的内存大小只与操作系统的位数有关,32位---4个字节,,64位---8个字节
3.可修改性:数组的首地址是数组名,内存的分配原则是从(地址)高到低分配,从(地址)低到高存储,所以数组中越靠后的元素地址越高,此时我们使用 首地址 + (数组名) + n (n代表单元,单元的字节取决于该指针变量的类型)
4.首地址是常量地址,不可赋值更改
5.指针本质上是一个变量,只不过该变量是用来存储地址,值可以更改,也就是地址可以更改(又叫做指针重定向)
6.使用 p--是地址 *p--是取值 *p = --是赋值,赋的值是指向的变量类型所对应的值
}
今天的练习作业:
// 1.定义一个整型数组,包含20个元素,通过指针随机赋值[15, 30],请通过指针求数组中所有元素的最大值,最小值,和,平均值
int array[20] = {0},max = 0,min = 30,sum = 0,avg = 0;
int *pArray = array;
printf("数组中的元素为:\n");
for (int i = 0; i < 20; i++) {
*(pArray + i) = arc4random() % 16 + 15;
sum = sum + *(pArray + i);
printf("%d ",*(pArray + i));
if (max < *(pArray + i)) {
max = *(pArray + i);
}
if (min > *(pArray + i)) {
min = *(pArray + i);
}
}
avg = sum / 20;
printf("\n元素的最大值为:%d 最小值为:%d 和为:%d 平均值为:%d",max,min,sum,avg);
// 2.定义六个字符串,即六行的二维字符数组,分别找出六个字符串首地址, 用冒泡排序(升序),然后打印出排序好的字符串
// 例如: //定义六个字符串,即六行的二维字符数组
// char a[6][100]={“chi","hong","huang","lv","lan","dian"};
char a[6][100] = {"chi","hong","huang","lv","lan","dian"};
char *p[6] = {0};
for (int i = 0; i < 6; i++) {
p[i] = a[i];
}
for (int i = 0; i < 6 - 1; i++) {
for (int j = 0; j < 6 - 1 - i; j++) {
if (strcmp(p[j], p[j + 1]) > 0) {
char *temp = {0};
temp = p[j];
p[j] = p[j + 1];
p[j + 1] = temp;
}
}
}
printf("排序好的数组各个元素为:");
for (int i = 0; i < 6; i++) {
printf("%s \n",p[i]);
}
//
//
//
}