前言
今天看到一个C语言程序题的时候,觉得有的时候我们即使把答案写出来了,但是过程具体是怎么实现的可能并不太清楚,所以我这里会将这道程序题讲的比较清楚一点,希望对指针困惑的同学能理解。
提示:以下是本篇文章正文内容,下面案例可供参考
一、数组名是什么?
数组名其实是数组的首地址,假设 char a[]=“3e434”;这里的a本质上就相当于是&a[0]。为什么会这样?原因很简单:大多数用到数组名的地方,编译器会将数组名变成指向数组的首元素的指针。 由于这篇文章并不是解释数组名的,如果还没搞懂,大家可以参考一个这个链接:数组名和指针的关系
二、程序解析
1.程序如下
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void fun(char *w, int n);
int main()
{
char *p = "1234567";
fun(p, strlen(p));
puts(p);
system("pause");
return 0;
}
void fun(char *w, int n)
{
char *s1 = w, *s2 = w + n - 1;
while (s1 < s2)
{
char t;
t = *s1++;
*s1 = *s2--;
*s2 = t;
}
}
2.分析代码
如果对数组名不太熟悉的话,可能会读不懂第一行代码。 char *p = "1234567"; 其实是相当于:下面的两行代码,指的其实是指针变量p指向a[0]。
char a[] = "1234567";
char *p = a;
这里简单的提示一下:fun(p, strlen(p)); 这行代码中的strlen的长度是7不是8,因为其不会算上\0字符,与操作运算符sizeof的结果不一样。
下面我们来简单的读一下我们定义的函数fun中的代码
char *s1 = w, *s2 = w + n - 1;
不知道大家对于这个while语句中的s1和s2是否有些疑问?
while (s1 < s2)
{
char t;
t = *s1++;
*s1 = *s2--;
*s2 = t;
}
这里的s1和s2其实是地址值,由于数组在内存中是线性存储的,s1本质上是a[0]的地址,s2是a[6] 的地址。 细心的会发现,为什么这里s1的地址值调试出来,旁边会有一个字符串? 其实原因很简单,这里我写了几句简单的代码来帮助理解。本质上: C语言在处理这种字符串时候,默认当成了常量字符串,即const类型。 继续来分析我们的程序:
t = *s1++;
*s1 = *s2--;
*s2 = t;
这里的t=*s1++需要注意一下,相当于我们书上的i++的问题,它是先赋值再自增,所以t=*s++于t=*s是等价的。s1相当于解引用,将a[0]的值赋给t,然后执行s1=s+1,即将a[6]的值赋给a[1],最后再将t的值赋给s2=*s2-1,即a[5]的值。然后后面一直这样循环,直到不满足条件。最终的答案是1711717
总结
这道题目中其实串联了很多小的知识点,有一个小知识点理解错误,可能答案就会出不来。 指针可以直接指向地址然后对其地址上的值进行修改。在某些时候会给程序的效率带来质的飞跃,但使用指针时一定要清楚,指针指向了哪里,考虑会不会给数组中的其他值带来印象,防止会有意想不到的结果出现。
|