初阶指针(2)
创始人
2024-04-10 02:50:03

初阶指针(2)

  • 4. 指针运算
    • 4.1 指针+-整数
    • 4.2 指针的关系运算
    • 4.3 指针-指针
  • 5. 指针和数组
    • 6. 二级指针
    • 7. 指针数组

4. 指针运算

  • 指针± 整数
  • 指针-指针
  • 指针的关系运算

4.1 指针±整数

代码一

通过指针进行打印数组内容

#include 
int main()
{double arr[5] = { 0 };double* p = arr;int i = 0;for (i = 0; i < 5; i++){printf("%lf ", *(p + i));}return 0;
}
//-------------------
//编译器运行结果为
//0.000000 0.000000 0.000000 0.000000 0.000000

这里面用到了指针±整数

代码二

#define N_VALUES 5
float values[N_VALUES];
float *vp;
//指针+-整数;指针的关系运算
for(vp=&values[0];vp<&values[N_VALUES];)
{*vp++ = 0; 
}

*vp++中后置++的运算优先级高于*,后置++先进行运算,再进行解引用vp加之前的地址。

*vp++;  <==>  int* p = vp++;*p;

4.2 指针的关系运算

代码一

将数组的5个空间赋值为0

#define N_VALUES 5
float values[N_VALUES];
float *vp;
for(vp = &values[N_VALUES]; vp > &values[0];)
{*--vp = 0; 
}

注:虽然出现了values[5],但是并没有进行越界访问操作,仅仅是进行指向作用。

代码简化, 这将代码修改如下:

for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--) 
{*vp = 0; 
}

实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准并不保证它可行。

标准规定:

允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。

4.3 指针-指针

指针减指针有意义

指针加指针无意义

#include 
int main()
{int arr[10] = { 0 };printf("%d\n", &arr[9] - &arr[0]);printf("%d\n", &arr[0] - &arr[9]);return 0;
}
//----------------
//编译器运行结果为
//9
//- 9

两个指针相减的前提是,指针指向的是同一块连续的空间。

指针减指针的值是两个指针之间的元素个数的绝对值。

如果随意两个指针进行相减结果是不可预测的。

实现模拟strlen函数

代码一:非递归

#include 
int my_strlen(char* str)
{int count = 0;while ((*str)!='\0'){count++;str++;}return count;
}
int main()
{char arr[] = "abcdef";int len = my_strlen(arr);printf("%d\n", len);
}

代码二:递归

#include 
int my_strlen(char* arr)
{if (*(arr + 1) != '\0'){return 1 + my_strlen(arr + 1);}return 1;
}
int main()
{char arr[] = "abcdef";int ret = 0;ret = my_strlen(arr);printf("%d", ret);return 0;
}

代码三:指针减指针

#include 
int my_strlen(char* str)
{char* start = str;while ((*str) != '\0'){str++;}return (str-start);
}
int main()
{char arr[] = "abcdef";int len = my_strlen(arr);printf("%d\n", len);
}
//------------------------
//编译器运行结果为
//6

当知道了首元素的地址和字符\0的地址,两地址相减就是字符串的个数。

简化版

#include 
int my_strlen(char* str)
{char* start = str;while (*str){str++;}return (str - start);
}
int main()
{char arr[] = "abcdef";int len = my_strlen(arr);printf("%d\n", len);
}
//------------------------
//编译器运行结果为
//6

字符’\0’的ASCII码值就是0,所以直接while(*str)

5. 指针和数组

我们看一个例子:

#include 
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };printf("%p\n", arr);printf("%p\n", &arr[0]);return 0;
}
//---------------------
//编译器运行结果为
//00F7FA38
//00F7FA38

可见数组名和数组首元素的地址是一样的。

结论:数组名表示的是数组首元素的地址。(2种情况除外,数组章节讲解了)

那么我们可以把数组名当成地址存放到一个指针中,我们使用指针来访问数组。

打印数组内容

代码一

#include 
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int* p = arr;int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);for (i = 0; i < sz; i++){printf("%d ", *(p + i));}return 0;
}
//--------------------
//编译器运行结果为
//1 2 3 4 5 6 7 8 9 10

代码二

#include 
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int* p = arr;int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);for (i = 0; i < sz; i++){printf("%d ", *p);p++;}return 0;
}
//--------------------
//编译器运行结果为
//1 2 3 4 5 6 7 8 9 10

数组可以通过指针进行访问,但是数组和指针不是一个东西。

数组能够存放一组数据,开辟连续的空间,数组的大小取决于元素类型和个数。

指针是一个变量,是用来存放地址的。

联系就是:

数组名是地址(指针)。

数组把首元素的地址,交给一个指针变量后可以通过指针来访问数组。

6. 二级指针

int main()
{int a = 10;int* p = &a;  //p就是指针变量,一级指针变量int** pp = &p;  //pp就是二级指针return 0;
}

a的地址放在p中,p的地址存放在pp中,p是一级指针变量,而pp是二级指针变量。

a是int类型,int*类型:*代表p是一个指针,int代表指向对象是int类型。

int**:外部的*代表pp是一个指针,而指向对象是int*类型。

二级指针的应用

#include 
int main()
{int a = 10;int* p = &a;  //p就是指针变量,一级指针变量int** pp = &p;  //pp就是二级指针*p = 20;printf("a=%d\n", a);**pp = 30;printf("a=%d\n", a);return 0;
}
//-------------------
//编译器运行结果为
//a = 20
//a = 30

访问a可以使用*p或者**pp

对于二级指针的运算有:

*pp 通过对pp中的地址进行解引用,这样找到的是 p ,*pp 其实访问的就是 p 。

int b = 20;
*pp = &b;//等价于 p = &b;

**pp 先通过 *pp 找到 p ,然后对 p 进行解引用操作: *p ,那找到的是 a

**pp = 30;
//等价于*p = 30;
//等价于a = 30;

7. 指针数组

指针数组是指针还是数组?

答案:是数组。是存放指针的数组。

数组我们已经知道整形数组,字符数组。

而指针数组是用来存放指针的数组。

int main()
{//整型数组—存放整型的数组int arr[10];//字符数组—存放字符的数组char arr2[5];//指针数组—存放指针的数组int* arr3[5];  //存放整型指针的数组char* arr4[5];  //存放字符指针的数组return 0;
}

指针数组的应用

代码一

#include 
int main()
{int a = 10;int b = 20;int c = 30;int* arr[3] = { &a,&b,&c };int i = 0;for (i = 0; i < 3; i++){printf("%d ", *(arr[i]));}return 0;
}
//-----------------
//编译器运行结果为
//10 20 30

代码二

用一维数组模拟一个二维数组

#include 
int main()
{//用一维数组模拟一个二维数组int arr1[] = { 1,2,3,4,5 };int arr2[] = { 2,3,4,5,6 };int arr3[] = { 3,4,5,6,7 };int arr4[] = { 4,5,6,7,8 };int* arr[4] = { arr1,arr2,arr3,arr4 };int i = 0;for (i = 0; i < 4; i++){int j = 0;for (j = 0; j < 5; j++){printf("%d ", arr[i][j]);}printf("\n");}return 0;
}
//----------------
//编译器运行结果为
//1 2 3 4 5
//2 3 4 5 6
//3 4 5 6 7
//4 5 6 7 8

这就是初阶指针的所有语法,希望大家都能学会这部分的内容。

相关内容

热门资讯

金风科技股价涨5.68%,新疆... 12月23日,金风科技涨5.68%,截至发稿,报17.85元/股,成交15.64亿元,换手率2.67...
三维天地跌2.09%,成交额2... 12月23日,三维天地盘中下跌2.09%,截至10:16,报34.61元/股,成交2920.46万元...
易方达纳斯达克100ETF(Q... 数据显示,12月22日,易方达纳斯达克100ETF(QDII)(159696)获净申购354.86万...
金风科技股价涨5.68%,万家... 12月23日,金风科技涨5.68%,截至发稿,报17.85元/股,成交15.70亿元,换手率2.68...
金风科技股价涨5.68%,民生... 12月23日,金风科技涨5.68%,截至发稿,报17.85元/股,成交15.72亿元,换手率2.68...