C语言面试题常见问题

最近开始面试,但是面试笔试总是喜欢问奇怪的问题,下面我总结一下常见面试题。


1.下述三个有什么区别?

char * const p;
char const * p
const char *p
答案:
char * const p; // 常量指针, p 的值不可以修改
char const * p // 指向常量的指针,指向的常量值不可以改
const char *p // char const *p
解释:
下面用代码去解释
    int ab = 12;
    int ee = 0;
    int *const p = &ab;
    p = ⅇ
    *p = ee;
    const int *pp = &ab;
    pp = ⅇ
    *pp = ee;
    printf("*p=%d,*pp =%d\r\n",*p,*pp);
在终端输出得出以下结果
test.c:31:7: error: assignment of read-only variable ‘p’
   31 |     p = ⅇ
      |       ^
test.c:35:9: error: assignment of read-only location ‘*pp’
   35 |     *pp = ee;

2.解释下列输出结果

char str1[] = "abc"; char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char *str5 = "abc";
const char *str6 = "abc";
char *str7 = "abc";
char *str8 = "abc";
cout << ( str1 == str2 ) << endl;
cout << ( str3 == str4 ) << endl;
cout << ( str5 == str6 ) << endl;
cout << ( str7 == str8 ) << endl;         

答案

结果是:0 0 1 1

解释:

str1,str2,str3,str4 数组变量,它们有各自的内存空间;
str5,str6,str7,str8 指针,它们指向相同的常量区域。
因为str1和str2两个字符数组都存储在栈空间上,但两者地址值不相等。而str3 和str4并非字符数组而是字符指针,并不分配存储区,其后的“abc”以常量形式存于常量区,str3 和 str4 是指它们指向的地址的首地址,而它们自己仅是指向该区首地址的指针,所以相等

3.以下代码中的两个 sizeof 用法有问题吗?

void UpperCase( char str[] ) // 将 str 中的小写字母转换成大写字母
{ 
    for( size_t i=0; i<sizeof(str)/sizeof(str[0]); ++i ) 
    if( 'a'<=str[i] && str[i]<='z' ) 
    str[i] -= ('a'-'A' ); 
} 
char str[] = "aBcDe"; 
cout << "str 字符长度为: " << sizeof(str)/sizeof(str[0]) << endl; 
UpperCase( str ); 
cout << str << endl;

答案:

函数内的 sizeof 有问题。根据语法, sizeof 如用于数组,只能测出静态数组的大小,无法检测动态分配的
或外部数组大小。函数外的 str 是一个静态定义的数组,因此其大小为 6 ,函数内的 str 实际只是一个指向字符
串的指针,没有任何额外的与数组相关的信息,因此 sizeof 作用于上只将其当指针看,一个指针为 4 个字节,
因此返回 4
注意 : 数组名作为函数参数时 , 退化为指针 .
数组名作为 sizeof() 参数时 , 数组名不退化 , 因为 sizeof 不是函数 .

4.一个 32 位和64位的机器 , 该机器的指针是多少位
答案:
32位4个字节。
64位8个字节。

5.指出下面代码的输出,并解释为什么。(不错,对地址掌握的深入挖潜)

main() 
{ 
    int a[5]={1,2,3,4,5}; 
    int *ptr=(int *)(&a+1); 
    printf("%d,%d",*(a+1),*(ptr-1)); 
} 

答案:

输出:2,5

解释:

*(a+1 )就是 a[1] *(ptr-1) 就是 a[4], 执行结果是 2 5
&a+1 不是首地址 +1 ,系统会认为加一个 a 数组的偏移,是偏移了一个数组的大小(本例是 5 int
int *ptr=(int *)(&a+1);
ptr 实际是 &(a[5]), 也就是 a+5
原因如下:
&a 是数组指针,其类型为 int (*)[5];
而指针加 1 要根据指针类型加上一定的值,
不同类型的指针 +1 之后增加的大小不同
a 是长度为 5 int 数组指针,所以要加 5*sizeof(int)
所以 ptr 实际是 a[5]
但是 prt (&a+1) 类型是不一样的 ( 这点很重要 )
所以 prt-1 只会减去 sizeof(int*)
a,&a 的地址是一样的,但意思不一样, a 是数组首地址,也就是 a[0] 的地址, &a 是对象(数组)首地址, a+1
是数组下一元素的地址,即 a[1],&a+1 是下一个对象的地址,即 a[5].

 写一个标准宏,这个宏输入两个参数并返回较小的一个

#define Min(x,y) ((x)>(y)?(y):(x))


关键字static作用是什么

1.定义静态局部变量,作用域从函数开始到结束

2.在模块内的static函数只可以被这一模块内其他函数调用,这个函数的适用范围被限制在他的模块内

3.在类中,static成员变量属于整个类拥有,对类的的所有对象只有一份拷贝


关键字const有什么含义 

1.表示常亮不可以修改的变量

2.可以修饰参数,作为输入参数

3.修饰函数,以防以外的改动

4.修饰类的成员函数,不改变类中的数据成员.


 关键字 volatile 有什么含意?并举出三个不同的例子?

: 提示编译器对象的值可能在编译器未监测到的情况下改变。
例子 : 硬件时钟 ; 多线程中被多个任务共享的变量等

 


6. int (*s[10])(int) 表示的是什么?
答案:
int (*s[10])(int) 函数指针数组,每个指针指向一个 int func(int param) 的函数。

从前往后看:
第一个 int :表示返回值;
*s[10] :是一个指针数组,s是一个含有10个指针的数组;
第二个int:表示形参列表
把 ( * s[10])看成一个指针*p,*p(int)就表示一个函数指针;
则 int (*p)(int) 表示:函数指针,指向一个 int func(int param) 的函数;
故 int (*s[10])(int) :解读为:函数指针数组,每个指针指向一个 int func(int param)的函数。

 

  • 18
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值