C语言三道面试题

本文介绍了三道C语言面试题目,分别涉及指针运算、调试经验和安全编程。在指针运算中,分析了数组与指针的关系;调试经验部分通过一个实例展示了printf函数的可变参数特性;安全编程环节讨论了数组越界导致的隐患,并提出使用strncpy代替strcpy来避免此类问题。

1.考察指针运算

#include <stdio.h>

void main()
{
    int TestArray[5][5] = { {11,12,13,14,15},
                            {16,17,18,19,20},
                            {21,22,23,24,25},
                            {26,27,28,29,30},
                            {31,32,33,34,35}
                          };
    int* p1 = (int*)(&TestArray + 1);
    int* p2 = (int*)(*(TestArray + 1) + 6);

    printf("Result: %d; %d; %d; %d; %d\n", *(*TestArray), *(*(TestArray + 1)), 
                                           *(*(TestArray + 3) + 3), p1[-8], 
                                           p2[4]);
}


结果是11,16,29,28,26

提示
(1)&TestArray不仅是数组首地址,而且还包含了内存大小信息,&TestArray+1之后指向的是数组最后一个元素的后面。
(2)数组和指针运算的转换:*(a+i) ==> a[i] ,* (*(a+i)+j)==>a[i][j];

2.考察调试经验

#include<stdio.h>

void main()
{
    char* p = "hello world!";
    int a = (int)p;
    short s = 'c';

    printf("%c\n", (long)(*((int*)p)));
    printf("%s\n", a);
    printf("%s\n", &s);
}

输出的结果是
h
hello world!
c

你可能会疑惑,和想象输出的结果不一样,其实这主要是printf函数的第二个输入参数是可变参数的原因,可变参数函数无法确定参数的实际类型,可以看一下之前的这篇文章:
C语言函数参数的秘密(下)
分析:
1.首先,( * ((int*)p)),得到的是四个字节,hell,%c只取一个字节打印,所以打印了h。
2.变量a是四个字节,刚好存放了字符串的地址,%s打印的是字符串,因此后面的地址被printf解释为字符串的地址,打印出了字符串。
3.&s存放的是2个字节的地址,字符’c’一个字节,小端系统上内存存放方式是c0,大端系统存放的是0c,小端系统低地址放低位,先放低字节,再放高字节,即c0

3.考察安全编程

#include<stdio.h> 

int main(int argc, char *argv[]) 
{ 
    int flag = 0; 

    char passwd[10]; 

    memset(passwd,0,sizeof(passwd)); 

    strcpy(passwd, argv[1]); 

    if(0 == strcmp("Linuxpswd", passwd)) 
    { 
        flag = 1; 
    } 

    if( flag ) 
    { 
        printf("\n Password cracked \n"); //密码正确输出这个

    } 
    else 
    { 
        printf("\n Incorrect passwd \n"); //密码错误输出这个
    } 

    return 0; 

}

这定义的密码passwd是九位数,那么超过十位数会发生什么呢?
数组越界,将密码越界错误之后,第一次输出了错误,但是第二次输入任意的密码,居然输出了密码正确。
int flag = 0; 和 char passwd[10]; 都是定义在栈上面的,初始化的时候,flag是0,然后经过字符串拷贝函数strcpy(passwd, argv[1]); 之后呢,如果数组越界了那么flag空间的内容就会被改写了,falg就不是0了,如果是一个非零值,那么会输出密码正确。
所以最好使用strncpy这个函数,而不是strcpy使用零作为结束符,如果将strcpy(passwd, argv[1]);改写为`strncpy(passwd, argv[1],9); ,那么就可以避免这个问题了,限制密码拷贝为9个字符,更加安全。
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值