1.长度和宽度
sizeof和strlen的区别
#include<stdio.h>
#include<string.h>
int main(){
char s[]="i love linux\0\0\0";
int a=sizeof(s);
int b=strlen(s);
printf("%d %d",a,b);
}
这个结果是16和12.其原因是sizeof比strlen多记录\0的数量。其中字符串原本自带了\0所以sizeof得到的a会比b多4.
2.箱子大小和装入物品的顺序
struct test1{
int a;
short b;
double c;
};
struct test2{
short b;
int a;
double c;
};
这两个是输出是相同的,都是16,这个考的是结构体对齐的问题,相关的知识点可以在我之前几年的题解中得到解释 。 第一个test1开始的int 占四个字节然后short占两个,因为八个算在一起所以不会移走,但double站八个字节所以只能挪走,所以是十六个字节,第二个test2相似
3.输出二维数组
#include<stdio.h>
#define M 3
#define N 2
int main(){
int **addOne(int a[M][N]);
int a[M][N]={{1,1},{2,2},{3,3}};
int i,j;
int **b = addOne((int **)a);
for(i=0;i<M;i++)
for(j=0;j<N;j++)
printf("%d\t",*((int *)b+N*i+j));
}
int **addOne(int a[M][N]){
int **b =(int **)malloc(M*sizeof(int *));
for (int i=0;i<M;i++)
b[i]=(int *)malloc(N*sizeof(int));
int i,j;
for(i=0;i<M;i++)
for(j=0;j<N;j++)
*((int *)b+N*i+j) = *((int *)a+N*i+j) + 1;
return b;
}
4.
- 传值:传值,实际是把实参的值赋值给行参,相当于copy。那么对行参的修改,不会影响实参的值 。
- 传址: 实际是传值的一种特殊方式,只是他传递的是地址,不是普通的赋值,那么传地址以后,实参和行参都指向同一个对象,因此对形参的修改会影响到实参
可以看作定义一个a、b,*p、*p2,其中a、b与*p、*p2的地址空间是一样的,那么当*p1、*p2被修改时,a、b也会跟着发生变化,因为此时二者占用了同一块空间,当任意一者使空间里的内容发生变化时,二者都会做相同变化。
题目在曾经的博客中存在相似的题,就不再进行阐述了
5.
#include<stdio.h>
unsigned sum(unsigned n){return n?sum(n-1)+n:0;
}int main(){
printf("%u\n",sum(100));
}
表达式? 结果1:结果2
表达式返回true 返回结果1,否则返回结果2。
在这里是对1-100进行一个累加,即每次判断都会得到ture,所以会一直得到n-1的结果所以得到最后的结果便是对其累加
5050
6.
#include<stdio.h>
void func(void) {
short a = -2;
unsigned int b = 1;
b += a;
int c = -1;
unsigned short d = c * 256;
c <<= 4;
int e = 2;
e = ~e | 6;
d = (d & 0xff) + 0x2022;
printf("a=0x%hx\tb=0x%x\td=0x%hx\te=0x%x\n", a, b, d, e);
printf("c=0x%hhx\t\n", (signed char)c);
}
int main(){
func();
}
a=0xfffe b=0xffffffff d=0x2022
e=0xffffffff c=0xf0
1 a=-2(10)=1111 1111 1111 1110(2)=fffe(16)
2 b=1(10)
3 b=-1(10) ->1111 1111 1111 1111 1111 1111 1111 1111(2)=ffffffff(16)
4 c=-1(10)
5 d=-250(10) ->1111 1111 0000 0110(2)
6 c=-16(10)=1111 1111 1111 1111 1111 1111 1111 0000(2)=fffffff0(16)
7 e=2(10)
8 e=1111 1111 1111 1111 1111 1111 1111 1111(2)=ffffffff(16)
9 d=0000 0000 0000 0110 + 0010 0000 0010 0010 =0010 0000 0010 1000(2)=2028(16)
所以最后输出a=0xfffe b=0xffffffff d=0x2028 e=0xffffff c=0xf0 (signed char)使c的结果保留1个字节
7.输出结果为10 4 9
8.
(1)func2对指针执行间接访问并企图改变指针指向的对象的值,错误,func3企图将指针指向别处,错误,func4对指针执行间接访问并企图改变指针指向的对象的值,并且企图将指针指向别处,犯了两个错误。
(2)个人认为const int和iint const没有区别
(3)个人认为const int *和int const *也没有区别
举个例子:
1、const int *a
这里const 修饰的是int,而int定义的是一个整值
因此*a 所指向的对象 值 不能通过 *a 来修改,但是 可以重新给 a 来赋值,使其指向不同的对象
eg:
const int *a = 0;
const int b = 1;
int c = 1;
a = &b //ok! 额外:注意不能通过a 来修改 b值
a = &c //ok! 额外:虽然c本身不是一个常量
*a = 2 //erro! 为题就在这里,不能修改通过 *a 所指向的对象值,最后赋值得对象是c,因此不能通过*a 来修改c值。
9.
char* convert(char*);
int main(void)
{
char *str="XiyouLinux Group 2022";
char *temp=convert(str);
printf("%s",temp);
return 0;
}
char* convert(char* str)
{
int i=0;
char te,aa[100]="\0";
while(te=*(str+i))
{
if(te>='a'&&te<='z')
te-=32;
else if(te>='A'&&te<='Z')
te+=32;
aa[i++]=te;
}
char* p=aa;
return p;
}
13.输出为Welcome to xiyou linux group 2021
解释:
大小端问题
可以参考19年的题解
14.
(1)预处理阶段。预处理器(cpp)根据字符#开头的命令,修改原始的C程序。
(2)编译阶段。将c语言文件从高级语言转为汇编语言。
(3)汇编阶段。将汇编语言转化为二进制语言。
(4)链接阶段。将使用的头文件与本文件链接起来。
15.
栈区内存由编译器自主分配和释放,堆区内存由程序员手动分配和释放。