欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

实验室暑假第一次测试总结

程序员文章站 2022-06-23 07:54:28
前言这个第一次测试写下来总体来说不太理想,尽管学长已经很有心承上启下来安排题目,规划以后学习路线,但我对于以前的基础题还是忘的有点多,或者对于前半年所学的自我感觉有失偏颇,总之,没有写好,以后要多加努力啊。。1. 阅读下面代码段,回答问题typedef struct tag_unimportant {char *t2;int t1;} A;void func(A *a){a = (A *)malloc(sizeof(A));a->t1 = 0x20200011;a-&g...

前言

这个第一次测试写下来总体来说不太理想,尽管学长已经很有心承上启下来安排题目,规划以后学习路线,但我对于以前的基础题还是忘的有点多,或者对于前半年所学的自我感觉有失偏颇,总之,没有写好,以后要多加努力啊。。

1. 阅读下面代码段,回答问题

typedef struct tag_unimportant {
	char *t2;
	int t1;
} A;
void func(A *a)
{
	a = (A *)malloc(sizeof(A));
	a->t1 = 0x20200011;
	a->t2 = (char* )&(a->t1);
	*(a->t2) = 0x00;
	//strcpy(a->t2, "xiyoulinux");
}
int main(int argc, char *argv[])
{
	A *a;
	func(a);
	printf("%x\n", a->t1);
	//printf(“%s\n”, a->t2);
	return 0;
}

1). 以下代码段存在问题, 请在不修改结构体定义,不减少功能的前提下对此对此代码
中存在的问题进行修改并说明修改原因。
2). 修改正确后,写出输出结果并说明原因
3). 将注释加入程序, 能正确运行吗, 如果能, 输出结果是什么, 并说明原因
4). sizeof(A)的结果是什么,为什么,再定义一个 int 类型的 t3, 定义的位置影响结果吗,
说明理由。

  1. 第一问有两种解法,你要么是去主函数开辟结构体堆大小,要么改用二级指针进行地址值传递

改正后

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct tag_unimportant
{
    char *t2;
    int t1;
} A;
void func(A **a)
{
    //*a =(A *)malloc(sizeof(A));
    (*a)->t1 = 0x20200011;
    *((*a)->t2) = 0x00;
    strcpy((*a)->t2, "xiyoulinux");

}
int main(int argc, char *argv[])
{
    A *a;
   	a=(A*)malloc(sizeof(A));
    func(a);
    printf("%x\n", a->t1);
    printf("%s\n", a->t2);
}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct tag_unimportant
{
    char *t2;
    int t1;
} A;
void func(A **a)
{
    *a =(A *)malloc(sizeof(A));
    (*a)->t1 = 0x20200011;
    (*a)->t2 = (char* )&((*a)->t1);
    *((*a)->t2) = 0x00;
    strcpy((*a)->t2, "xiyoulinux");
}
int main(int argc, char *argv[])
{
    A *a;
    func(&a);
    printf("%x\n", a->t1);
    printf("%s\n", a->t2);
}
  1. 第二问略
  2. 第三问有点意思,首先我们先明确结构体里面t1所在的地址值为0x20200011
    下一步强转(char*)后t2所在的地址值为0x00000011
    因为一开始t1的类型是int,占四个字节,所在的内存分别是0x0000,0x0001,0x0002,0x0003
0x0000 0x0001 0x0002 0x0003 
  11     00      20    20   

小端模式从低地址读到高地址
强转后为

0x0000 0x0001 0x0002 0x0003
  11     00      00     00 

char类型指针,占前面一个地址,即内存0x0000的内容,后面补齐三个字节
这时的t2是0x00000011,解引用赋值后为0x00,即为0

补:如果我们要强转(short*)或者(float*)呢,请写出答案

之后strcpy()复制xiyoulinux到t2,但是由于t2空间大小,可能会栈溢出,为不可知的值,这是一个不安全的方法,建议改用memcpystrncpy

2.分析代码并说明:

a. 最终输出多少次"hello, world?"
b. printf 加上换行符,最终输出多少次"hello, world?";
c. 最终将产生共多少个进程。

int main(int argc, char *argv[])
{
	for (int i = 0; i < 2; i++)
	{
		pid_t pid = fork();
		printf("hello, world?");
	}
}

a. 8
b.6
c.4

  1. 第一个的问题是printf是向标准输出(stdout)输出你要打印的东西,而默认的stdout是行缓存的,
    所以当你打印的东西不够一行(没有\n)的时候,这些信息是保存在stdout的buffer
    首先进行fork(),这样父进程和子进程的stdout的buffer就都包含有你没有打印出来的内容(因为没有换行符),第二次fork(),原先的父进程产生新的子进程,原先的子进程产生新的子程,这时就有四个进程,缓冲区里面有四个hello world,经过两次循环,buffer中的内容会被打印出二次
  2. 第二题同理,只不过打印的东西够了一行(有\n结束符),于是在第一次fork()时就会打印两个,接着fork()后有四个进程,便会打印四个,一共六个

3. 僵尸进程和孤儿进程是什么?分明写代码复现。

4. 有两个线程在并发执行以下代码段,其中 g 是 int 类型的全局变量。请问当两个线程都执行完毕该代码段后,g 的值的取值范围为

for (int i = 1; i <= 50000; i++)
{
	g += 1;
}

50000-100000
这方面有点涉及编译器原理,可能解释的有点不准确
50000 : 第一个线程+1,第二个线程也+1,这种情况虽然二个线程都对g加1,但显然只加了一次。所以到最后只加50000次
100000 : 第一个线程的for结束,再到第二个线程的for结束,一共执行100000次

5.编写一个至少具有三个线程的程序(称之为线程 A、B 和 C),其中线程 A 输出字符’A’,线程 B 输出字符’B’,线程 C 输出字符’C’。使得最终输出结果为“ABCABCABC…”。

#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<semaphore.h>
#include<stdlib.h>

sem_t sem[3];
 
void* fun1(void* arg)
{
     while(1)
     {
           sem_wait(&sem[0]);
           printf("A");
           sem_post(&sem[1]);
     }
}
void* fun2(void* arg)
{
     while(1)
     {
          sem_wait(&sem[1]);
          printf("B");
          sem_post(&sem[2]);
     }
}
void* fun3(void* arg)
{
      while(1)
      {
          sem_wait(&sem[2]);
          printf("C");
          sem_post(&sem[0]);
      }
}
int main()
{
      pthread_t tid,cid,gid;

      sem_init(&sem[0],0,1);
      sem_init(&sem[1],0,0);
      sem_init(&sem[2],0,0);
 
      pthread_create(&tid,NULL,fun1,NULL);
      pthread_create(&cid,NULL,fun2,NULL);
      pthread_create(&gid,NULL,fun3,NULL);
 
      pthread_join(tid,NULL);
      pthread_join(cid,NULL);
      pthread_join(gid,NULL);
 
      sem_destroy(&sem[0]);
      sem_destroy(&sem[1]);
      sem_destroy(&sem[2]);
 }

是时候复习一下信号量了,我拿锁没写出来。。害

本文地址:https://blog.csdn.net/weixin_45819130/article/details/107597854