一.运行下面的代码,输出结果是什么,解释原因。
int i;
int main(int argc, char *argv[])
{
i--;
if (i > sizeof(i))
{
printf(">\n");
}
else
{
printf("<\n");
}
return 0;
}
解答:i是int 型变量占4字节空间,所以sizeof(i)=4
因为定义为全局变量且i未初始化,则i默认为0
输出<
二.执行下面的代码段,输出结果和你预想的一样吗,谈谈你对宏的理解。
#define A 2 + 2
#define B 3 + 3
#define C A * B
int main(int argc, char *argv[])
{
printf("%d\n", C);
return 0;
}
解答:11
因为宏定义只是表面的复制替换,在这个过程不会有任何的运算操作,所以c=2+2*3+3=11
三.分析下面程序的输出结果
int main(int argc, char *argv[])
{
char str[] = "Welcome to XiyouLinuxGroup";
printf("%zu %zu\n", strlen(str), sizeof(str));
return 0;
}
解答:26 27
%zu输出size_t型。size_t在库中定义为unsigned int
四.在程序中执行此函数,输出结果是什么,在同一程序中多次执行该函数,产生的输出结果是否相同?
void fun()
{
int x = 0;
static int num = 0;
for (int i = 0; i < 5; i++)
{
x++;
num++;
}
printf("x = %d num = %d\n", x, num);
}
解答:在前两篇文章有相同的题型,在此便不再赘述。(变量的生命周期)
五.分析以下程序,推测并验证其作用.
int main(int argc, char *argv[]) { int number; unsigned mask; mask = 1u << 31; scanf("%d", &number); while (mask) { printf("%d", (number & mask) ? 1 : 0); mask >>= 1; } return 0; }
****解答:将十进制转化为二进制
mask = 1u << 31;表示无符号整型1进行左移位运算。
& 与 两个位都为1时,结果才为1 | 或 两个位都为0时,结果才为0 ^ 异或 两个位相同为0,相异为1 ~ 取反 0变1,1变0 << 左移 各二进位全部左移若干位,高位丢弃,低位补0 >> 右移 各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移) 可以直接看做1*2**31,右移位运算可以看做/2**(n)
六.分析一下程序并说明其作用。
int main(int argc, char *argv[])
{
char *str = "Xiyou Linux Group";
printf("%c\n", *str + 1);
return 0;
}
解答:输出*str可以视作一个字符串数组,那么*str取出的是字符'X',字符‘X’+1转化为ASCII码再%c输出便是Y.
七.以下程序段的运行结果是什么,你知道怎么判断两个浮点数是否相同吗?
int main(int argc, char *argv[])
{
double a = 3.14;
float b = a;
if ((float)a == b)
{
printf("Xiyou");
}
if (a != b)
{
printf("LinuxGroup\n");
}
return 0;
}
解答:LinuxGroup
float:-3.4E38(-3.4*10^38)~3.4E38(3.4*10^38) 4字节
double:-1.7E308(-1.7*10^308)~1.7E308(1.7*10^308) 8字节
用==从语法上说没错,但是本来应该相等的两个浮点数由于计算机内部表示的原因可能略有微小的误差,这时用==就会认为它们不等。应该使用两个浮点数之间的差异的绝对值小于某个可以接受的值来判断判断它们是否相等,比如用。
if (fabs(price - p) < 0.000001)
来代替
if (price == p)
定义一个精度,用差的绝对值比较,在精度范围内就认为是相等的;大小可以直接比较
****八.运行下列的代码,解释运行结果并谈谈自己的理解。
int main(int argc, char *argv[])
{
int a[6] = {0x6f796958, 0x694c2075, 0x2078756e, 0x756f7247, 0x30322070,0};
printf("%d\n", printf("%s", (char *)a));
return 0;
}
解答:
Xiyou Linux Group 2020
printf的返回值是输出字符个数。
a的输出结果是Xiyou Linux Group 20,%d输出printf的返回值,printf的返回值是20,里面的printf意味着有20个字符,而Xiyou Linux Group 20正好20个字符。
a[6]的里面是十六进制的ascii码,还有大小端的知识。 ##这里不会,copy了其他同学的解释..
九.分析下列程序的输出,解释其原因。
int main(int argc, char *argv[])
{
int a[2][3] = {{5, 7}, {5, 2}};
int b[2][3] = {5, 7, 5, 2};
int c[2][2] = {{5, 7}, {5, 2}};
int d[2][2] = {5, 7, 5};
printf("%d %d\n", a[1][1], b[1][1]);
printf("%d %d\n", c[1][1], d[1][1]);
return 0;
}
解答:2 0 2 0
二维数组复制可以不打“{}”但是定义数组的时候,部分初始化,剩余元素自动补0;
char arr[10];//局部定义数组或者变量的时候不赋值么,数组或者变量的内容是不确定的
一个是没赋值,一个是没赋完值,注意两者的区别。
十.执行下面的程序段,其输出结果是什么,请根据相关知识,解析其原因。
int main(int argc, char *argv[])
{
int a = 1;
printf("%d\n", *(char *)&a);
}
解答:1
我们试着来解剖*(char*)&a
char*定义一个指向char型变量的指针,那么&a被定义为了该指针,我们可以暂时把它看作p,
因为p=&a所以我们又可以得出p指向a,解p指针,我们得到了a.在这个过程中a被强制转化为了字符,
也就是0000 0000 0000 0000 0000 0000 0000 0001,计算机小端输出为1.(大小端知识可以去看21年的最后一题)
十一.下面程序段的输出结果是什么,若取消第三行的const注释,a数组还能被修改吗?如果取消6,8行的注释,程序还能正常运行吗,试着解释其原因。
int main(int argc, char *argv[])
{
/*const*/ char a[] = "XiyouLinux\0";
char *b = "XiyouLinux\0";
a[5] = '\0';
// b[5] = '\0';
printf("%s\n", a);
// printf("%s\n",b);
return 0;
}
解答:不能
因为a被const定义不可以修改
字符串指针b指向的内容是不可修改的,用字符串指针定义的是存放在静态存储区,是常量,不可更改。
#摘自网络
现在我们有一个C语言文件(hello.c):
#include <stdio.h> int main() { printf("hello, world!\n"); return 0; }现在我们将执行以下命令将源文件(hello.c)转化为可执行目标文件(hello):
gcc -o hello hello.c我们使用的是gcc编译器驱动程序完成的。这个转化的过程可分为四个阶段完成。执行这四个阶段的程序(预处理器、编译器、汇编器和链接器)一起构成了编译系统。
hello.c(源程序[文本])->预处理器(cpp)->hello.i(修改了的源程序[文本])->编译器(ccl)->hello.s(汇编程序[文本])->汇编器(as)->hello.o(可重定位目标程序[二进制])->链接器(ld)->hello(可执行目标程序[二进制])
- 预处理阶段。预处理器(cpp)根据字符#开头的命令,修改原始的C程序。结果就得到了另外一个C程序,通常是以.i作为文件扩展名。
- 编译阶段。编译器(ccl)将文本文件hello.i翻译成文本文件hello.s,它包含一个汇编语言程序。汇编程序是非常有用的,它位不同高级语言的不同编译器提供了通用的输出语言。
- 汇编阶段。汇编器(as)将hello.s翻译成机器语言指令,将这些指令打包成一种叫做可重定位目标程序的格式,并将格式保存在目标文件hello.o中。如果我们使用文本编辑器打开hello.o文件,将会看到一堆乱码。
- 链接阶段。hello程序调用了printf函数,它是每个C编译器都会提供的标准C库中的一个函数。printf函数存在于一个名为printf.o的单独的预编译好了的目标文件中,而这个文件必须以某种方式合并到我们的hello.o程序中,链接器(ld)就是处理这种合并,结果就得到了hello文件。它是一个可执行文件,可以被加载到内存中,由系统执行。