C语言面试题及详细解释

本文探讨了C语言编程中常见的挑战,包括数组操作、指针理解、内存管理等关键概念,并提供了具体的代码示例来帮助读者深入理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 写出运行结果(这道题很NB)

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

 

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

 

           char a[] = "abc";

           char b[] = {'d', 'e', 'f'};

 

           printf("a slen=%d,b slen=%d/n", strlen(a),strlen(b));

          printf("a = %s, b = %s/n", a, b);

           printf("asize len = %d, bsize len = %d/n", sizeof(a),sizeof(b));

           return 0;

 }

运行结果:

a slen = 3,b slen = 6

a = abc, b = defabc

asize len = 4, bsize len = 3

解释:

程序栈示意图:

/0

c

b

a

f

e

d

 

 高地址

 

 

 

 <--a

 

 

 

 <--b

 低地址

 

 

程序栈内存分配原则:从高地址->低地址分配;

我们可以把两个数组a和b看作两个变量,因此a的地址比b的高;

同时,数组内部每个元素的赋值又是从低地址到高地址进行的,因此就有了以上的程序栈示意图。

我们可以把数组名看成是一种特殊的指针(其实更类似于引用),它们所指向的位置(数组第一个元素)如上图,

而strlen(char* p)的内部实现就是++p直到*p=='\0',因此就有了第一行的输出结果(返回的长度不包括结束字符'\0')。

同理,第二行的输出结果也很好理解了。

第三行就是考察对sizeof操作符的掌握了,sizeof(a)就是求的数组a所占的内存字节数,就是4(包括了字符'\0')。

(这些都是我自己的理解,欢迎讨论)

 

 

 

 

2. 说出错误

void test() {

    char str[10];

    char* str1 = "0123456789";//alloc in the only read data area

    strcpy(str, str1); //array index overflow

}

注:数组越界,因为str1实际上有11个字符

 

3. 说出错误

void test() {

    char str[10], str1[10];

    for( int = 0; i < 10; i++){ //memset(str,0,sizeof(str))

//modif i< 10-1

            str[i] = 'a';

    }

    strcpy(str1, str); //出错,因为str不是'\0'结束的字符串

}

 

4. 写出程序的运行结果

#include <stdio.h>

 

int sum(int a) {

        static int b = 3;

        b += 2;

        return(a + b);

}

 

int main(void) {

        int a = 2;

        int i;

 

        for (i = 0; i < 5; i++) {

            printf("%d, ", sum(a));

        }

        return 0;

}

 

7, 9, 11, 13, 15,

考察的是函数内的静态变量,只会被初始化一次,以后每次调用该函数都不会再重置。

 

5.写出运行结果

#include <stdio.h>

 

int main(void)  {

        int a[3];

           a[0] = 0;

           a[1] = 1;

           a[2] = 2;

 

           int *p, *q;

           p = a;

           q = &a[2];

 

           int c = a[q - p];

//同类指针相减结果:

//两指针之间间隔所指类型元素(变量)的个数,所以两指针差值等于所得地址差值除以所指类型所占的字节数;

           printf("value c = %d/n", c++);

           printf("value c = %d/n", c);

 

           return 0;

}

 

value c = 2

value c = 3

 

6 写出运行结果

#include <stdio.h>

#include <string.h>

 

#define STRCPY(a, b)    strcpy(a##_p, #b)

#define STRCPY1(a, b)   strcpy(a##_p, b##_p)

 

int main(void)  {

        char var1_p[20];

        char var2_p[30];

 

        strcpy(var1_p, "aaaa");

        strcpy(var2_p, "bbbb");

 

        STRCPY1(var1, var2);

        STRCPY(var2, var1);

 

        printf("var1 = %s/n", var1_p);

        printf("var2 = %s/n", var2_p);

 

        return 0;

}

 

var1 = bbbb

var2 = var1

 

7.不用除法(即不能使用"/"号)和库函数,计算285 / 16的商和余数, 要求效率尽量高.

#define NUM_SHIFT       4

int inta = 285;

int left;

       

left = inta & ((1L << NUM_SHIFT) - 1);//(10000-1) ===>1111,按位与运算,只保留低4位,就是除以16的余数

inta = inta >> NUM_SHIFT;// 右移一位相当于除以2,右移4位就是除以16

 

11.指出下面程序段的错误

void teststr(char* p) {

 char str[16];

 int n;

 assert(NULL != p);

 sscanf(p, "%s%d", str, n); // n->&n

 if (0 == strcmp(str, "something")) {

 ...

 }

}

 

8.指出下面程序段的错误

void test2() {

 char string[10], str1[10];

 int i;

 for(i=0; i<10;i++) {

        str1[i] ='a';

 }

 strcpy(string, str1);

}

错误:数组越界;

解决方法:

    方法一:

#define STR_LEN     10

void test2() {

 char string[10], str1[10];

 int i;

 memset(str1, 0, sizeof(str1));  //全部置0(对应字符'\0')

for(i=0; i<STR_LEN-1; i++) {

        str1[i] ='a';

 }

 strcpy(string, str1);

}

    方法二:

#define STR_LEN     10

void test2() {

 char string[10], str1[10];

 int i;

 for(i=0; i<STR_LEN-1; i++) {

        str1[i] ='a';

 }

 str1[STR_LEN] = ‘/0’;

 strcpy(string, str1);

}

 

9.交换两个值

int i = 5;

int j = 8;

i^=j; // 按位异或运算

j^=i; //j = j ^ i

i^=j; // I = I ^ j

  

10.写出程序的结果

struct abc {

char t:4; //low bit

char k:4;

unsigned short i:8;

unsigned long m;

} // add __attribute__((packed)) sizeof(abc) = 0.5+0.5+1+4=6

    No add : sizeof = 0.5+0.5+1+2+4=8 //2: auto align ,add 2

sizeof(abc)=?(不考虑边界对齐)6

 

11.请指出下列程序中的错误并且修改

void get_memory(char *p, int size) {

 p = (char *)malloc(size); //p is copyer str's

}

void test(void) {

 char *str = NULL;

 get_memory(str,100);

 strcpy(str, "hello world");

 printf(str);

}

 

A:错误--参数的值改变后,不会传回

get_memory并不能传递动态内存,Test函数中的 str一直都是 NULL。

strcpy(str, "hello world");将使程序崩溃。

修改如下:

方法一:

char *get_memory(int size){

 char *p=(char *)malloc(size);

 return p;

}

void test(void){

 char *str = NULL;

 str = get_memory(100);

 strcpy(str,"hello world");

 printf(str);

}

方法二:

void get_memory(char **p, int size){

    *p = (char *)malloc(size);

 

12.假一个硬件寄存器是的地址为0x50000000, 宽度为32位,给出其寄存器在C语言中读/写宏定义

#define LREG (*(volatile unsigned int *)0x50000000)

#define READ_LREG LREG

#define WRITE_LREG(ch) (LREG = (unsigned int)(ch))

 

13.写下面sizeof 的求值

A. 32位为例, 计算sizeof的值.

     char str[] = "Hello";

     char   *p = str;

     int     n = 10;

请计算

sizeof (str) =   6 //include '/0'           

sizeof (p) =   4          

sizeof (n) = 4

 

B. void func( char str[100]){

   请计算

   sizeof(str) =   4

}

 

C. void *p = malloc( 100 );

请计算

sizeof(p) = 4

 

D. struct date {

    int year;

    int months;

    int days;

};

struct date *d;

请计算

d = malloc(sizeof(struct date));

sizeof(d) = 4

sizeof(*d) = 12

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值