个人中心
首页 > 面试有戏 > 面试题库 > 正文

有关C语言的指针面试题!

来源:五百丁 作者:五百丁小编

C语言的指针面试题“指针可以访问内存,函数中传递形参时加个*号可以改变内容”,这基本就是很多初学者对指针的全部理解。但是一用起来就到处出错,总是“云里雾里”,今天专门地说说指针的那些事。


有关C语言的指针面试题!.jpg


1、指针的“两要素”


指针有一个初始地址,*操作取地址中的内容,++操作移动指向内存中的位置,移动的大小由指针指向元素的类型决定。


(1)指针在内存中是什么?


所有类型的指针在内存中都是32bit(32位系统),保存了一个地址,相当于一个unsigned int。

这一点一定要记牢了,指针就是个32位的数字,里面放的是个内存地址。


(2)指针指向的元素是什么?


指针可以指向任意的类型,常见的包括基本类型,指针,数组,函数。


指针的定义很简单,就是在指向类型前面加个,但是对于需要注意\、()、[]的优先级问题。

指向基本类型的指针

  int x = 2;

  int *p = &x;

指向指针的指针

  int **q = &p;

首先p是个指针,存放了x的地址。&p是存放指针p的地址(不要忘了p就是个32位的数字,也是保存在内存中),二级指针q也是个32位的数字,不过里面放的就是p的地址。

指向数组的指针

  int data[8];

  int *p = data;

  int data[10][8];

  int (*p)[8] = data;//指针

  int *p[8] ;//数组

定义数组的指针会稍微麻烦一点,首先数组是 int data[8],直接加上*号就变成了int *data[8]。 但是由于[]的优先级比高,所以int \data[8]相当于int *(data[8]),更直白一点就是 int* (p[8]),它是个数组,数组包含8个元素,每个元素类型是int *。


为了改变优先级,加个括号编程int (*data)[8],data首先和*结合表明它是个指针。int (*data)[8]把(*data)拿掉就变成了int[8],说明它指向一维数组int[8]。

总结下就是: int (*p)[8] 是指针,指向一维数组int[8]; int *p[8] 是数组,数组包含8个元素,每个元素类型是int * 。

指向函数的指针

  int func(int, float);

  int (*p)(int, float) = func; 

  int *func(int, float); 

函数指针的定义也是一样,在函数int func(int, float)的名字上加个*号,就变成了int *func(int, float)。但是由于func右边的()优先级比左边的高,相当于int\ func(int, float),所以它是个函数,返回的参数是个int* 。


解决的办法和数组指针一样,在func上加个括号就变成了int (*func)(int, float)。 需要注意下的就是函数名称其实就是函数执行的入口地址,所以加不加&都一样。


函数指针在qsort中经常用到,和C++ stl中的函数对象非常像。


2、指针的操作


c语言中只有一维数组,但数组中元素类型可以是任意的。所以多维数组本质上还是一维数组,只不过数组中每个元素又是一个数组。


(1)取值 *


指针是个地址,用*号可以根据类型取到地址中的内容。


如果是int *p, 那么从起始地址开始取4个字节转化为int值;如果是double,那么从起始地址开始取8个字节转化为double。


由于数组在内存中的地址是连续的,所以通过++来移动指针可以很方便地访问下一个元素。


(2)移动 ++


指针始终指向第一个元素的起始位置,通过++指向下一个元素的起始位置。由于数组中指向的元素类型是不同的,同样是p+1根据元素类型不同移动的字节也相差很大。这里的下一个元素可能是下一个int,下一个double或者下一个数组,看看下面二维的例子。


对于二维数组int matrix[3][10],可以通过下面两种方式来访问matrix[1][1]:


*(matrix[1] + 1)


*( * ( matrix + 1) + 1)


matrix是一个数组,该数组拥有3个数组类型的元素,其中每个元素都是一个拥有10个整型元素的数组。 matrix + 1移动的是一个包含10个整型的数组,所以matrix + 1直接移动到第二行。


具体可以看下面:


但matrix+ 1) + 1后面的+1移动的就仅仅是一个整型:


总结:*( * ( matrix + 1) + 1) 由于指针指向的每个元素类型不同,matrix + 1移动的是一个包含10个整型的数组, 而matrix+ 1) + 1第二个+1移动的是一个整型。


3、数组名和指针的区别


数组名可以认为是个常量指针,指向数组第一个元素的地址,是个左值不可被改变。


对于int a[10]; a++这样的操作是非法的,因为数组已经分配好了内存,而a是它的起始地址,肯定是无法改变的。


由于数组只能在栈或者堆上分配内存,所以数组名也就只能指向堆或者栈上的内存。而指针可以指向堆区、栈区、字符常量区。所以char a[]=”abc”;和char *p = “abc”分配内存所在的区域不同,一个在栈上,一个在字符常量区。


4、函数形参中的指针


在函数形参中,数组名被解释为指向数组的第一个元素的指针。


对于一维数组,以下几种方式都相同:


void func(int *p);


void func(int p[]);


void func(int p[100]);


但对于多维数组,由于数组中每个元素本身是另外一个数组,因此编译器需要知道它的维数,这样才能够支持++操作。例如,int matrix[3][10],每次matrix++移动的是一个数组,那么这个数组到底有多少维是需要知道的,所以二维数组的列数需要给出。


voint matrix[3][10];

void func(int **p)

{

    printf("a=%d,\n",p[1][1]);

}

int main(int argc, char *argv[])

{

    matrix[1][1] = 20;

    func(matrix);

    return 0;

}

上面的程序无法正确运行,因为在func函数中无法知道p[1]也就是p+1,这里的+1到底应该是多大的距离。


函数正确的声明方式如下:


void func(int p[3][10]);


void func(int p[][10]);


void func(int (*p)[10]);


1

二维码

1.五百丁遵循行业规范,任何转载的稿件都会明确标注作者和来源;

2.五百丁的原创文章,请转载时务必注明文章作者和"来源:五百丁",不尊重原创的行为五百丁或将追究责任;

3.作者投稿可能会经五百丁编辑修改或补充。

相关推荐

Word简历模板

  • 最美简历合集
  • WORD简历模板
  • 线轴简历模板 清爽风格
  • 图形化创意简历模板合集

大家感兴趣的内容

客服在线时间:9:00-18:00

Copyright © 2014-2016 500d.me. All Rights Reserved.

个人中心 - 帮助中心 - 网站地图 - 粤ICP备14072413号