数组指针,指针数组
#include<stdio.h>
int main()
{
int a = 100;
int *p1 = &a; // 整型指针
char ch = 'A';
char *p2 = &ch; // 字符型指针
int arr[5] = {1, 3, 5, 7, 9};
int *p3 = arr; // 整型指针,指向整型1
int (*p4)[5] = &arr; // arr整个数组的地址
// 数组指针
int *p5[5];
printf("size: %ld\n", sizeof(p5)); // 5*8=40字节
char *str1 = "hello";
printf("str1: %s\n", str1);
// 字符串数组
char *str[5] = {"hello", "world", "nihao", "hahaha", "xixixi"};
printf("str[0]: %s\n", str[0]);
printf("str[1]: %s\n", str[1]);
printf("str[2]: %s\n", str[2]);
printf("str[3]: %s\n", str[3]);
printf("str[4]: %s\n", str[4]);
return 0;
}
函数指针,指针函数
#include<stdio.h>
// 计算和(函数的声明)
int func_sum(int a, int b);
int *func_1(int a);
int main()
{
// 函数调用原理:根据<函数入口地址>去执行对应函数。
int c1 = func_sum(100, 200);
printf("c1: %d\n", c1);
// 函数类型:返回值 + 形参列表(函数头)
// 函数名就是函数的入口地址。
int (*p1)(int, int) = func_sum;
int c2 = p1(300, 400);
printf("c2: %d\n", c2);
// 假设已知某个函数的入口地址为 0x000000FF
// (一般用于硬件代码中,因为软件程序中函数的地址都是随机分配的。)
// int (*p2)(int, int) = 0x000000FF;
// int c3 = 0x000000FF(300, 400); // 直接调用入口地址为 0x000000FF的函数
// printf("c3: %d\n", c3);
int *p2 = func_1(100);
printf("p2: %p\n", p2);
return 0;
}
int *func_1(int a)
{
int *p1 = &a;
printf("p1: %p\n", p1);
return p1;
}
// 计算和(函数的定义)
int func_sum(int a, int b)
{
return a+b;
}
函数的传递
#include<stdio.h>
// 值传递(只是将数值100, 200传参)
void func_swap1(int a, int b);
// 地址传递(将数值本身的地址传递过去)
void func_swap2(int *a, int *b);
int main()
{
int n1=100, n2=200;
printf("n1:%d n2:%d\n", n1, n2);
// func_swap1(n1, n2); // 值传递,不能修改变量本身
func_swap2(&n1, &n2);
printf("n1:%d n2:%d\n", n1, n2);
return 0;
}
// 地址传递(将数值本身的地址传递过去)
// int *a = &n1;
// int *b = &n2;
void func_swap2(int *a, int *b)
{
int c;
c = *a;
*a = *b;
*b = c;
printf("func_swap: a:%d b:%d\n", *a, *b);
}
// 值传递(只是将数值100, 200传参)
// int a = n1;
// int b = n2;
void func_swap1(int a, int b)
{
int c;
c = a;
a = b;
b = c;
printf("func_swap: a:%d b:%d\n", a, b);
}
==================== 1.地址偏移量概念 ========================
指针算术运算,可以跟数组形式相互转换。
*(p+i) <==> p[i]
备注:
int a[5];
printf("%d ", *(a++));
printf("%d ", *(a=a+1));
int a[5] = {1, 3, 5, 7, 9};
printf("a : %p\n", a); // 数组首元素地址
printf("&a : %p\n", &a); // 数组本身地址
// 上述两个地址在数值上是一样的,但是类型不相同。
printf("a+1 : %p\n", a+1); // 向右偏移4字节(类型:int *)
printf("&a+1: %p\n", &a+1); // 向右偏移20字节(类型:int (*)[5])
2.数组指针、指针数组、函数指针、指针函数 ========================
int (*p4)[5]; // 该指向指向 int [5]类型的数组
作用:一般用于二维数组访问。
int *p4[5]; // 该数组存储着5个指针(类型为 int *)
(数组三要素:连续内存+具体长度+相同类型)
作用:存储多个值,指向多个数据
int (*p1)(int, int) = func_sum; // 该指针指向函数 func_sum
作用:直接通过指针调用函数。(如回调函数)
int *func_1(int a) // 返回值为int *
如果返回值为 void *,表示返回无值型指针(任意类型指针)。
循环遍历二维数组
#include<stdio.h>
// *(p+i) <==> p[i]
int main()
{
// int arr[2][3] = {1, 3, 5, 2, 4, 6};
int arr[2][3] = {{1, 3, 5}, {2, 4, 6}}; //更为规范的写法
// int *p1 等同于 int (*p1)
// int *p1 = arr; // 错误写法。类型不匹配。
// int * = int (*)[3]
// 整型指针 = 数组指针
int *p2 = &arr[0][0]; // 类型匹配
// int * = int *
// 整型指针 = 整型指针
int (*p3)[3] = arr; // 类型匹配
// int (*)[3] = int (*)[3]
// 数组指针 = 数组指针
// 1.通过数组名访问
int i, j;
for(j=0; j<2; j++)
{
for(i=0; i<3; i++)
printf("%d ", arr[j][i]);
// printf("%d ", *(*(arr+j)+i));
// printf("%d ", *(arr[j]+i));
// printf("%d ", (*(arr+j))[i]);
// 上述四种写法效果一模一样。
// printf("%d ", *(arr+j)[i]); // 错误写法。因为[]优先级高于解引用*
printf("\n");
}
// 2.通过整型指针访问
printf("==============================\n");
for(i=0; i<2*3; i++)
// printf("%d ", *p2++);
// printf("%d ", *(p2+i));
printf("%d ", p2[i]);
printf("\n");
// 3.通过数组指针访问
printf("==============================\n");
for(j=0; j<2; j++)
{
for(i=0; i<3; i++)
// printf("%d ", p3[j][i]); // arr[j][i]
printf("%d ", *(*(p3+j)+i));
// printf("%d ", *(p3[j]+i));
// printf("%d ", (*(p3+j))[i]);
// 上述四种写法效果一模一样。
printf("\n");
}
return 0;
}
循环遍历一维数组
#include<stdio.h>
int main()
{
int a[5] = {1, 3, 5, 7, 9};
// int *p1 = &a[0]; // 定义指针,指向首元素a[0]
int *p1 = a; // 数组名就是首元素地址
// int * = int * 类型匹配!
printf("1: %p\n", p1);
for(int i=0; i<5; i++) // 0 1 2 3 4
{
// 写法1.1:指针本身进行偏移
// printf("%d ", *p1); // 对指针进行解引用
// p1++; //p1 = p1+1; //p1+=1;
// 写法1.2
// printf("%d ", *p1++); // ++优先级更高,但是它作为后缀,必须在运算结束后再自加
// printf("%d ", *(p1++)); // 等同于上一行
// printf("%d ", (*p1)++); // 错误写法。解引用后都是获得数据1。
// 写法2:指针进行运算
// printf("%d ", *p1+i); // 错误写法。解引用*的优先级高于+
// printf("%d ", *(p1+i)); // 正确写法。
// printf("%d ", *(i+p1)); // 正确写法。
// 写法3:指针运算(数组形式,地址偏移量)
// printf("%d ", p1[i]);
// printf("%d ", i[p1]);
// printf("%d ", a[i]);
// printf("%d ", i[a]);
// printf("%d ", *(a+i));
// printf("%d ", *(i+a));
// printf("%d ", *(a++)); //错误写法:数组名不能自增自减。*(a=a+1)
}
printf("\n");
int arr[2][3] = {1, 3, 5, 2, 4, 6};
printf("2: %p\n", p1);
return 0;
}