C语言基本功修炼秘籍第5节,初学者福音,几个C语言指针的问题详解
发表于: 2019-07-20 17:43:23 | 已被阅读: 27 | 分类于: C语言
鉴于很多C语言初学者都觉得指针非常难,本文将初学者常常觉得迷惑的地方以问答的形式解答,希望能够对读者有所帮助。
小明定义了一个C语言函数 int f(int * ),为什么 f(&5) 不能正常工作呢?
如果希望传递 5 给函数 f(),在C99中,可以使用下面这种方法:
f( (int[]){5} );
上面这行C语言代码相当于定义了一个数组,并且数组只有一个元素 5,函数 f() 接收到的参数是该数组,只不过这一过程中的数组名没有“显示”。
抛开C99的这个特性,C语言调用 f(&5) 就不能这么写了,而是需要借助变量:
int five = 5;
f(&five);
在C语言中,接受某个值指针的函数是有可能通过该指针修改该值的(即使程序员无此打算,C语言还是会一直这么认为),因此只有变量才能胜任。在C语言中,常数是只读的,只能作为右值,& 运算符是不能处理常数 5 的,f(&five) 会引发编译错误。
表达式 * p++ 增加了 p 指向的数值,还是指针 p 本身?
C语言中的 ++ 和 -- 运算符的优先级高于 * 运算符,所以
小明想使用指针操作数组里的数值,下面这段C语言代码有什么问题?
小明预计程序会输出 3,但是程序却输出了“垃圾值”,他的C语言代码如下,请看:
int array[5], i, *ip;
for(i = 0; i < 5; i++)
array[i] = i;
ip = array;
printf("%d\n", *(ip + 3 * sizeof(int)));
为什么上述C语言程序没有按照小明的预期输出?
小明是“聪明反被聪明误”了,他发现数组 array 是 int 型的,所以在指针加数上乘上了 sizeof(int)。其实,C语言中的指针加法运算会
printf("%d\n", *(ip + 3));
这样他的C语言程序就会输出数组 array 的第 3 个元素了。事实上,使用指针 ip 访问数组 array 中的元素时,也可以以“数组的形式”进行,例如:
printf("%d\n", ip[3]);
这样也就清楚了,小明原本的写法相当于
小明使用 char * 指针指向 int 型数组,为什么下面这行C语言代码就不正常了呢?
小明的C语言代码是下面这样的,他发现这段代码甚至都不能编译通过,为什么呢?
int main()
{
int arr[] = {1, 2, 3, 4, 5};
char *p = (char *)arr;
((int*)p)++;
return 0;
}
可能有部分C语言编译器可能做了非标准扩展,能够编译上述代码。
小明写出
p = (char *)((int *)p + 1);
或者以更简单的形式:
p += sizeof(int);
再或者,也可以多写一行C语言代码:
int *ip = (int *)p;
p = (char *)(ip + 1);
虽然有多种方法可以实现小明的想法,但是仍然应该尽量避免使用不恰当类型的指针操作数据。
小结
C语言的大多语法都是简单易懂的,这常常会给初学者一种“别人都说C语言难,我看也不过如此”的感觉。但是这种感觉常常会停止在初学者学到指针时,这是一些读者跟我说的。为此,本节讨论了几个比较典型的初学者会遇到的问题,并做了较为详细的解析。
本专栏是C语言基本功修炼秘籍,对指针的剖析自然是少不了的,接下来几节,将更加深入的探讨指针的用法,敬请关注。