面试经典-C语言之数组名分析
2013-04-17 20:59
232 查看
在腾讯春季实习生招聘笔试的时候遇到这么一个问题:
对于这个题目,我当时的分析是这样的,对于数组名a,它是一个int*指针常量,指向数组第一个元素的地址,既然是指针常量,a+sizeof(int)即为a+4,肯定是不可以表示a[1]的,B显然是可以的,对于C答案,就出现疑惑了,对一个指针取地址应该是int **类型,那么(int*)&a 应该表示指向存放a指针的区域的指针,看起来好像与a[1]毫不相干,所以C应该是不行的(实际证明是可以的),对于D答案,同样的道理,好像是不行的,因此答案似乎是ACD.
出人意料的是,答案尽然是A而已,这是为什么?
好吧,那是因为&a和a指向的是同一地点,如果有这个结论,得到答案A就不足为奇了。我记起来当初学sizeof函数的时候,向当时教C语言的老曹头问过了一个问题,为什么sizeof(a)的值不是4而是数组的大小呢,比如说这个例子里面就是20而不是4,那么,关于数组名,到底有哪些特性呢?
数组名是一个指针常量,指向数组的第一个元素,但是当数组作为参数传入函数时,数组名的这一特性消失,可以做自增自减等操作。
例如,对于下面这段代码:
![](http://images.cnitblog.com/blog/385532/201304/17205940-5b747719442241f6afa89ffed09707ef.png)
提示只有左值(lvalue)才能自增。而对于以函数名作为参数输入时,这一常量特性消失,如下面代码运行就没有问题:
[/code]
数组名和数组名取地址的指向的位置是一样的,但是它们有区别,以上面声明的int a[10]为例,a表示指向整数的指针,而&a表示指向数组的指针,下面这段代码清楚地说明了这一问题:
[/code]
相应的输出如下:
![](http://images.cnitblog.com/blog/385532/201304/17205944-debacc8c39d44e0ea5c32d7b2a24b4e7.png)
可以看出a和&a数值上是一样的,&a+1相较于a多了20个字节的距离,这正好是一个数组的长度。
sizeof(a)不是指针所占空间的大小,而是指数组a所占空间的大小。
给定一个数组int a[10]; 下面哪些不可以表示a[1]的地址?
A. a+sizeof(int)
B. &a[0]+1
C. (int*)&a+1
D.(int*)((char*)&a+sizeof(int))
对于这个题目,我当时的分析是这样的,对于数组名a,它是一个int*指针常量,指向数组第一个元素的地址,既然是指针常量,a+sizeof(int)即为a+4,肯定是不可以表示a[1]的,B显然是可以的,对于C答案,就出现疑惑了,对一个指针取地址应该是int **类型,那么(int*)&a 应该表示指向存放a指针的区域的指针,看起来好像与a[1]毫不相干,所以C应该是不行的(实际证明是可以的),对于D答案,同样的道理,好像是不行的,因此答案似乎是ACD.
出人意料的是,答案尽然是A而已,这是为什么?
好吧,那是因为&a和a指向的是同一地点,如果有这个结论,得到答案A就不足为奇了。我记起来当初学sizeof函数的时候,向当时教C语言的老曹头问过了一个问题,为什么sizeof(a)的值不是4而是数组的大小呢,比如说这个例子里面就是20而不是4,那么,关于数组名,到底有哪些特性呢?
数组名是一个指针常量,指向数组的第一个元素,但是当数组作为参数传入函数时,数组名的这一特性消失,可以做自增自减等操作。
例如,对于下面这段代码:
#include <stdio.h>int main()[/code]
{
int a[5]={1,2,3,4,5};
a++;
}
![](http://images.cnitblog.com/blog/385532/201304/17205940-5b747719442241f6afa89ffed09707ef.png)
提示只有左值(lvalue)才能自增。而对于以函数名作为参数输入时,这一常量特性消失,如下面代码运行就没有问题:
#include <stdio.h>void Func(int a[5]);
[/code]
int main()
{
int a[5]={1,2,3,4,5};
Func(a);
}
void Func(int a[5])
{
a++;
}
数组名和数组名取地址的指向的位置是一样的,但是它们有区别,以上面声明的int a[10]为例,a表示指向整数的指针,而&a表示指向数组的指针,下面这段代码清楚地说明了这一问题:
#include <stdio.h>void Func(int a[5]);
[/code]
int main()
{
int a[5]={1,2,3,4,5};
printf("The value of a is %X\n",a );
printf("The value of &a is %X\n", &a);
printf("The value of a+1 is %X\n",a+1 );
printf("The value of &a+1 is %X\n",&a+1 );
int *p1=(int *)(a+4);
printf("%d\n",p1[-1] );
printf("%d\n",((int *)(a+4))[-1] );
int *p2=(int *)(&a+1);
printf("%d\n",p2[-1] );
//printf("%s\n",((int *)(&a))[1] ); //加上这句话会出错
相应的输出如下:
![](http://images.cnitblog.com/blog/385532/201304/17205944-debacc8c39d44e0ea5c32d7b2a24b4e7.png)
可以看出a和&a数值上是一样的,&a+1相较于a多了20个字节的距离,这正好是一个数组的长度。
sizeof(a)不是指针所占空间的大小,而是指数组a所占空间的大小。
相关文章推荐
- 面试点:C语言经典面试题(C语言面试题分析之五)
- c语言字符指针数组经典,此后不必再担心字符串问题.
- C语言数组与指针定义分析
- 曾经进公司面试的C语言有关指针和数组的笔试题
- 【LeetCode-面试算法经典-Java实现】【053-Maximum Subarray(最大子数组和)】
- c语言面试经典
- C语言中字符数组和字符串指针分析
- C语言中字符数组和字符串指针分析
- C语言经典面试题 与 C语言面试宝典
- 笔试面试算法经典-打印n个数组中最大的topk
- 曾经进公司面试的C语言有关指针和数组的笔试题
- c语言 数组的更好运用 经典冒泡排序法
- C语言中字符数组和字符串指针分析
- C语言中字符数组和字符串指针分析
- C语言中字符数组和字符串指针分析
- 从编译器角度分析C语言中数组名和指针的区别
- 10个经典的C语言面试基础算法及代码
- C语言中字符数组和字符串指针分析
- 曾经进公司面试的C语言有关指针和数组的笔试题
- 从编译器角度分析C语言中数组名和指针的区别