今天我们大家一起来学习指针运算
文章目录
1.指针运算
1.1指针± 整数
数组在内存中是连续存放的,只要知道第⼀个元素的地址,顺藤摸瓜就能找到后⾯的所有元素
for(i=0; i<sz; i++)
{
printf("%d ", *(p+i));//p+i 这⾥就是指针+整数
}
1.2指针-指针
//指针-指针
#include <stdio.h>
int my_strlen(char *s)
{
char *p = s;//(将字符串首元素的地址传给指针p)
while(*p != '\0' )//(当p地址等于\0时结束循环)
p++;
return p-s;//(得到字符串长度)
}
int main()
{
printf("%d\n", my_strlen("abc"));
return 0;
}
1.3指针的关系运算
//指针的关系运算
#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int *p = &arr[0];
int sz = sizeof(arr)/sizeof(arr[0]);
while(p<arr+sz) //指针的⼤⼩⽐较
{
printf("%d ", *p);//打印数组的每个元素
p++;
}
return 0;
}
2.野指针
2.1 概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
2.2指针未初始化
#include <stdio.h>
int main()
{
int *p;//局部变量指针未初始化,默认为随机值
*p = 20;
return 0;
}
2.3指针越界访问
#include <stdio.h>
int main()
{
int arr[10] = {0};
int *p = &arr[0];
int i = 0;
for(i=0; i<=11; i++)
{
//当指针指向的范围超出数组arr的范围时,p就是野指针
*(p++) = i;
}
return 0;
}
2.4指针指向的空间释放(空间被收回)
#include <stdio.h>
int* test()
{
int n = 100;
return &n;
}
int main()
{
int*p = test();
printf("%d\n", *p);
return 0;
}
3.规避野指针
NULL 是C语⾔中定义的⼀个标识符常量,
值是0,0也是地址,这个地址是无法使用的,读写该地址会报错。
只要是NULL指针就不去访问,
同时使用指针之前可以判断指针是否为NULL
4.assert 断言
assert.h 头文件定义了宏 assert() ,用于在运行时确保程序符合指定条件,
如果不符合,就报错终止运行。这个宏常常被称为“断言”。
assert(p != NULL);
它不仅能自动标识文件和出问题的行号,
还有⼀种无需更改代码就能开启或关闭 assert() 的机制
缺点是,因为引入了额外的检查,增加了程序的运行时间
5.传值调用和传址调用
写⼀个函数,交换两个整型变量的值
这里调用Swap2函数的时候是将变量的地址传递给了函数,
这种函数调用方式叫:传址调用。
#include <stdio.h>
void Swap2(int*px, int*py)
{
int tmp = 0;
tmp = *px;
*px = *py;
*py = tmp;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
printf("交换前:a=%d b=%d\n", a, b);
Swap2(&a, &b);
printf("交换后:a=%d b=%d\n", a, b);
return 0;
}
传址调用,可以让函数和主调函数之间建立真正的联系,
在函数内部可以修改主调函数中的变量;
所以未来函数中只是需要主调函数中的变量值来实现计算,就可以采用传值调用。
如果函数内部要修改主调函数中的变量的值,就需要传址调用。
练习
1.字符串逆序
写一个函数,可以逆序一个字符串的内容。
代码
#include<stdio.h>
#include<string.h>
void Reverse(char* str)
{
char* left = str;
char* right = str + strlen(str) - 1;
char tmp = { 0 };
while (left < right)
{
tmp = *left;
*left = *right;
*right = tmp;
left++;
right--;
}
}
int main()
{
char arr[7] = "abcdef";
printf("字符串逆序前:%s\n", arr);
Reverse(arr);
printf("字符串逆序后:%s\n", arr);
return 0;
}
运行结果
2.调整奇数偶数顺序
输入一个整数数组,实现一个函数,
来调整该数组中数字的顺序
使得数组中所有的奇数位于数组的前半部分,
所有偶数位于数组的后半部分。
代码
#include<stdio.h>
#include<string.h>
void Swap_arr(int arr[], int sz)
{
int left = 0;
int right = sz - 1;
int tmp = 0;
while (left < right)
{
while ((left < right) && (arr[left] % 2 == 1))
{
left++;
}
while ((left < right) && (arr[right] % 2 == 0))
{
right--;
}
if (left < right)
{
tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
}
}
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
printf("调换奇数偶数数据前:\n");
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
Swap_arr(arr,sz);
printf("调换奇数偶数数据后:\n");
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
运行结果
3.strlen模拟实现
代码
#include<stdio.h>
#include<assert.h>
int Strlen(const char * str)
{
int count = 0;
assert(str);
while (*str)
{
count++;
str++;
}
return count;
}
int main()
{
int ret = 0 ;
ret = Strlen("abcdef");
printf("长度:%d\n", ret);
return 0;
}
运行结果
总结
我们了解了指针的三种运算,知道野指针如何规避及assert断言,
明白指针在自定义函数里的传址调用
对指针(指针运算,野指针,assert断言,传值调用)的分享就到这里了,如果感觉不错,希望可以给博主点个赞或者关注,感谢大家的支持,成为我继续分享的动力,还有什么问题和建议可以在评论区评论,拜拜。