西邮 Linux 兴趣小组 2019 补纳面试题

1. 下面代码的输出是什么?试着解释原因,说出你的理解

struct A {
    long a;
    int b;
};
int main(int argc, char* argv[])
{
    struct A num = {0x6e694c756f796978,0x7875};
    char ch = '0';
    for(int i = 0; ch; i++)
    {
        ch = *((char *)&num + i);
        printf("%c",ch);
    }
    printf("\n");
    return 0;
}

num为struct A类型,0x6e694c756f796978为long类型,0x7875为int类型。

        本题是16进制的ascii码,大小端的问题,还有结构体地址的题。

        结构体的地址是相连的,所以a的地址后就是b的地址,所以根据根据地址一个个强制类型转换为char的地址,截取后得到的正好是一个字母的ascii,

for(int i = 0; ch; i++)
    {
        ch = *((char *)&num + i);
        printf("%x ",ch);
    }//输出78 69 79 6f 75 4c 69 6e 75 78 0 

可以看出正好按两位两位的反转了,int类型的在long后,这就是小端的输出。

        小端是低地址存储低字节,而long和int类型强制转化为char类型,就是截取最後面的地址,而小端模式下,最後面的地址正好存储低字节,就是数的最後位数,char类型为1字节,正好是2*8,正好是两个16进制的数字所占的。(大端模式是高地址存储低字节。)

        int类型强制转化为char类型里输出0是因为获取到了0,是因为16进制00为char的ascii的0,而ascii的0为“\0”,所以获取到先得到0输出,然后发现结束了,後面的值不会再输出。

比如:

int main(){
    int num=0x690078;
    char ch='0';
    for(int i = 0; ch; i++)
    {
        ch = *((char *)&num + i);
        printf("%c",ch);
    }
}

本来输出xi,结果中间加了00,只能输出x.

2. 改写代码,在不改变 const 的情况下尝试使用更多的方法改变b的值。

int main(int argc, char* argv[])
{
const int b = 10;
// 自行添加语句,改变变量b的值
return 0;
}
int main(int argc, char* argv[])
{
    const int b = 10;

//1。
    int*p=&b;
    *p=2;
    printf("%d\n",b);

//2.
    int a=*&b;
    a=2;
    printf("%d\n",b);
    
//...(摸个鱼)

    return 0;
}

3.阅读下面的代码,判断 a 中哪些元素被改变了,解释原因。

struct node {
    char a;
    int b;
    short c;
};
struct n {
    char a;
    int b;
};
int main(int argc, char* argv[])
{
    struct node a[2] = {{1,2,3},{4,5,6}};
    *(int *)((char *)a + 2 * sizeof(struct n)) = 100;
    return 0;
}

        a是结构体node的第一个元素,它的地址即结构体的首地址,所以a[2] = {{1,2,3},{4,5,6}},会修改结构体中的值。

struct node {
    char a;
    int b;
    short c;
};
int main(int argc, char* argv[])
{
    struct node a[2] = {{1,2,3},{4,5,6}};
    printf("%p %p &%p\n",&a->a,&a->b,&a->c);//0x7ffc694dbd60 0x7ffc694dbd64 &0x7ffc694dbd68
    printf("%d %d %d\n",a->a,a->b,a->c);//1 2 3

    return 0;
}

可以看出a,b,c三个不同类型储存了1,2,3。

        对于*(int *)((char *)a + 2 * sizeof(struct n)),这个地址未赋值100前是什么?

        sizeof(struct n)=8,(char*)a+2*sizeof(struct n)就是a[0]的地址加16*sizeof(char),即a[0]+4*sizeof(int),就是a[4](就是a[2]中的第5个数,这里用a[4]表示),即,*(int *)((char *)a + 2 * sizeof(struct n))=100,修改了a[4]的值。

4. 解释以下代码的输出结果。

void func(char* a)
{
    printf("%lu\n", sizeof(a)) ;
    printf("%lu\n", strlen(a)) ;
}
int main(int argc, char* argv[])
{
    char a[] = "hello world";
    char* b = "hello world";
    printf("%s", b);
    func(a);
    printf("%lu\n", sizeof(a));
    printf("%lu\n", strlen(a));
    return 0;
}

结果:hello world
8
11
12
11

sizeof的作用是获取该变量占据的空间大小(包括‘\0’),strlen的作用是获取该字符串的长度。

可以看出两个sizeof(a)的结果不一样,那么肯定有不同点,仔细观察,就会发现,函数func的参数是个指针,指针的占据空间(64位下)永远是8。

5. 解释以下代码的输出结果。

#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)
int main(int argc, char* argv[])
{
    printf("%s\n", h(f(1,2)));
    printf("%s\n", g(f(1,2)));
    return 0;
}

        在宏定义里,a##b就是把a,b联接起来,,#a就是把a转化成字串,并合并。

        那么h(f(1,2))=g(12)=12

        g(f(1,2))=f(1,2)

6. lala 和 nini 是好朋友。有一天 lala 获得了 n 个质量不同的蛋糕,lala 想和 nini 一起分 享,让两个人都吃到相同质量的蛋糕。但是有强迫症的 lala 不想破坏每块蛋糕的完整 性,请编写程序判断这 n 个蛋糕是否符合 lala 的要求。

        如有错误,请见谅。

int isaccord(double avge,double nums[],int size);
#define MAX 20
int main(){
    int n=0;
    double nums[MAX];
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%lf",&nums[i]);
    }
    
    for(int gap=n/2;gap>0;gap/=2){
        for(int i=gap;i<n;i++){
            double t=nums[i];
            int j=i-gap;
            while(j>=0&&nums[j]>t){
                nums[j+gap]=nums[j];
                j-=gap;
            }
            nums[j+gap]=t;
        }
    }
    double sum=0,avge=0; 
    for(int i=0;i<n;i++){
        sum+=nums[i];
    }
    avge=sum/2;
    
    int flag=isaccord(avge,nums,n);
    if(flag==1){
        printf("符合");
    }else{
        printf("不符合");
    }

    return 0;
}

int isaccord(double avge,double nums[],int size){
    int flag=0;
    double sum=0;
    for(int i=0;i<size-1;i++){
        sum=0;
        for(int j=i;j<size;j++){
            sum+=nums[j];
            if(fabs(sum-avge)<0.0001){
                flag=1;
                return flag;
            }
        }     
    }
    return flag;
}

        其实排序可以用qsort()函数,我只是练练手希尔排序,很久没写了。

7. 编写函数实现以下功能:

输入: 一行字符串

输出:逆序输出字符串中的单词,不保留开头与结尾的空格,相邻单词间仅保留一个 空格 样例(❐ 代表空格):

输入: ❐❐❐❐Hello❐❐everyone,❐we❐are❐xiyouLinuxer❐

输出:xiyouLinuxer❐are❐we❐everyone,❐Hello

void reversePrint(char*str);

int main(){
    char str[100];
    //  hello  everyone, we are xiyou xiLinuxer 
    gets(str);

    reversePrint(str);

    return 0;
}

void reversePrint(char*str){
    int l=strlen(str);
    for(int i=l-1;i>=0;i--){
        if(str[i]!=' '){
            str[i+1]='\0';
            break;
        }
        l--;
    }
    for(int i=l-1;i>=0;i--){
        if(str[i]==' '){
            printf("%s",&str[i+1]);
            if(str[i]!=str[i-1]){
                printf(" ");
            }
            if(str[i]==str[i-1]){
                str[i-1]='\0';
            }
            str[i]='\0';
        }
        if(i==0&&str[0]!=' '){
            printf("%s\n",&str[i]);
        }
    }
}

8. 下面这段程序有错吗?如果有错请指出并改正。

void func(char* p)
{
    p = (char* )malloc(sizeof(char));
}
int main(int argc, char* argv[])
{
    char* s = NULL;
    func(s);
    strcpy(s, "I love xiyou_linux");
    puts(s);
    return 0;
}

问题:1.改变一级指针,要通过二级指针。

        2.申请的内存没有释放,也没有检查是否申请成功。     

void func(char** p)
{
    *p = (char* )malloc(sizeof(char)*20);
    if(p==NULL){
        fprintf(stderr,"malloc error\n");
        exit(2);
    }
}
int main(int argc, char* argv[])
{
    char*s = NULL;
    func(&s);
    strcpy(s, "I love xiyou_linux");
    puts(s);
    return 0;
}

或者

char* func(char* p)
{
    p = (char* )malloc(sizeof(char)*20);
    if(p==NULL){
        fprintf(stderr,"malloc error\n");
        exit(2);
    }
    return p;
}
int main(int argc, char* argv[])
{
    char*s = NULL;
    s=func(s);
    strcpy(s, "I love xiyou_linux");
    puts(s);
    return 0;
}

9. 在不创建新节点的情况下,逆置一个已给的链表。

Node* reverse(Node*head){
    //我想不到不用新节点的办法,最多是只使用中间变量。
    Node*t1=NULL,*t2=NULL;
    t1=head->next;
    head->next=NULL;//截断
    while(t1!=NULL){
        t2=t1;
        t1=t1->next;

        t2->next=head;
        head=t2;
    }

    return head;
}

void print(Node*head){
    Node*d=head;
    while(d!=0){
        printf("%d ",d->val);
        d=d->next;
    }
    printf("\n");
}

int main(){
    Node*head=NULL;
    Node*p;
    Node*last=NULL;
    int num=0;

    do{
        scanf("%d",&num);
        if(num!=-1)
        {
            p=(Node*)malloc(sizeof(Node*));
            p->val=num;
            p->next=NULL;
            if(head){
                last->next=p;
            }
            else{
                head=p;
            }
            last=p;
        }
    }while(num!=-1);

    print(head);

    head=reverse(head);
    print(head);

    return 0;
}

10. 运行下列的代码,针对运行结果谈谈自己的理解。

int main(int argc, char* argv[])
{
    char c = -1;
    printf("%x\n", c);
    printf("%x %d\n",
    (unsigned char)c, (unsigned char)c);
}

运行结果:ffffffff
                ff 255

有符号数把最高位当做符号位无符号数则把最高位正常看待,
%x的输出,其实是把字符型转成16进制整型输出,

char中 -1:直接输出c,就是ffffffff,

在(unsigned char)下10000001,转化为补码就是1111 1111 ,即ff ff,也是255,    

如果字符型是有符号的,那么转成整型之后,内存占用32位 ,输出ffffffff

如果是有符号型,转换后就是认为是内存占8位,输出ff

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值