一.运行下面的代码,输出结果是什么,解释原因。
int i;
int main(int argc, char *argv[])
{
i--;
if (i > sizeof(i))
{
printf(">\n");
}
else
{
printf("<\n");
}
return 0;
}
这里会输出“>”这个符号,因为i是全局变量,会初始化为0,对sizeof(i),i为int类型,所以为4,
i--后i为-1,所以-1<4,输出“<”符号。
二.执行下面的代码段,输出结果和你预想的一样吗,谈谈你对宏的理解。
#define A 2 + 2
#define B 3 + 3
#define C A * B
int main(int argc, char *argv[])
{
printf("%d\n", C);
return 0;
}
宏是简单的替换,所以C=2+2*3+3=11,而不是c(2+2)*(3*3)
三.分析下面程序的输出结果
int main(int argc, char *argv[])
{
char str[] = "Welcome to XiyouLinuxGroup";
printf("%zu %zu\n", strlen(str), sizeof(str));
return 0;
}
%zu是size_t的输出类型,size_t是标准c库里定义的。
/* 32位 */
typedef unsigned int size_t;
typedef int ssite_t;
/* 64位 */
typedef unsigned long size_t;
typedef long ssize_t;
strlen()是获取该字符串的长度,而sizeof是获取该变量占据的字节数。
所以结果是26和27,sizeof比strlen多获取了“\0”占据的字节数。
(int argc.char*argv[])是命令行参数有关的感兴趣可以去了解。
四.在程序中执行此函数,输出结果是什么,在同一程序中多次执行该函数,产生的输出结果是否相同?
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);
}
num是static定义的静态局部变量,它的生命周期一直到本程序的结束,而作用域是本函数,本函数出去后,该变量就不能再调用,但多次调用该函数,num会承接上次调用该函数时的num的值,所以,num一直增加,而x每一次调用就从0开始。
五.分析以下程序,推测并验证其作用.
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的值是2^32次方,1在符号位上,将number与mask进行“&”位与运算,总共做32次,将number的二进制梅一位进行计算得出。
加上number为3,那么运算就是
1: 10000000 00000000 00000000 00000000
10000000 00000000 00000000 00000011//得到第一位的值
2: 01000000 00000000 00000000 00000000
10000000 00000000 00000000 00000011//得到第二位的值
…………
32: 00000000 00000000 00000000 00000001
10000000 00000000 00000000 00000011//得到第32位的值
六. 下面程序的运行结果是什么,请解释说明
int main(int argc, char *argv[])
{
char *str = "Xiyou Linux Group";
printf("%c\n", *str + 1);
return 0;
}
结果为:Y
*(str+1)的话就是:字符串的指针表示,*str为字符串指针,str就是字符串第一个字符的地址,printf("%c",*str)就是输出第一个字符,*(str+1)就是输出第二位字符处。
而*str+1,就是在*str值的基础上+1,而字符不能+1,所以会转换成ascii加1,X的ascii+1正好是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
因为计算机计算出来的小数点后的值是有精度的,常数赋值不会有问题,而经过计算的和常数赋值的比较会出现误差,计算的会有精度损失,这时候就需要用一个极小的值做比较大小(记得求绝对值,因为你可能不能确定哪一个大,哪一个小)。
例如:
#include<stdio.h>
#include<math.h>
int main(){
double a=1.14;
double b=0.9+0.24;
if(fabs(a-b)<0.00000001){
printf("True\n");
}else{
printf("False\n");
}
return 0;
}
八.运行下列的代码,解释运行结果并谈谈自己的理解。
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
a的输出结果是Xiyou Linux Group 20,%d输出printf的返回值,printf的返回值是20,里面的printf意味着有20个字符,而Xiyou Linux Group 20正好20个字符。
a[6]的里面是十六进制的ascii码,还有大小端的知识,根据输出结果看,我的是小端模式。
附送测试方法:
int main(){
int num = 0x12345678;
char cs = *(char*)#
// 低地址处是高字节,则为大端
if ( cs == 0x12 )
printf("大端");
else{
printf("小端");
}
}
九.分析下列程序的输出,解释其原因。
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
对a,是一个二维数组,相当于包含两个一维的数组,而第一个一维数组的第三个值没有赋,所以没有第三个值,第二个数组的第二位,即a[1][1],值为{5,2}中的2.
对b,也是一个二维数组,但是相较于a,没有{}包裹,所以第一个一维数组的有第三个值,为5,第二个一维数组的第2,3位没有赋值,所以没有b[1][1],未初始化,为随机数,0为巧合。
对c,是一个二维数组,包含的一维数组有两个值,所以它的值全赋了,按常输出,c[1][1]值为2.
对d,是一个二维数组,包含的一维数组有两个值,但它只赋了三个值,第四个未赋值,所以第四个数。d[1][1]为随机数,0为巧合。
十.执行下面的程序段,其输出结果是什么,请根据相关知识,解析其原因。
int main(int argc, char *argv[])
{
int a = 1;
printf("%d\n", *(char *)&a);
}
输出结果:1
(char*)&a,将a的地址强制转化为字符类型的指针,然后输出该地址的值的ascii码值,即将int类型4字节的,变成char类型的1字节的值,但在小端模式下(我前面说了),1的低地址存储在低字节,转化为char类型,没有变化。
十一.下面程序段的输出结果是什么,若取消第三行的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;
}
结果:Xiyou
按题目改都是错的(乐), 因为带const的都是常量,是为了防止自己乱改加的东西,不能更改,b是一个字符串指针,而字符串指针类似于const char b[],字符串指针指向的内容是不可修改的,用字符串指针定义的是存放在静态存储区,是常量,不可更改。
十二. c源程序->可执行文件过程,gcc
我上一个博客说过了,就不再说了。
对于gcc:浅显易懂的GCC使用教程——初级篇_大娱乐家-CSDN博客_gcc使用,我觉得这个讲的特别好,我讲也讲不这么清楚,所以我直接贴链接。
十三.仔细阅读下面这个函数,你可以看出这个函数的功能吗?试着理解算法原理,并尝试优化它。
void sort(int arr[], int size)
{
int i, j, tmp;
for (i = 0; i < size - 1; i++)
{
for (j = 0; j < size - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
这就是一个简单的冒泡排序,优化的话,我现在只能直接上快速排序了,乐,优化冒泡是我没想到的。
对于该冒泡排序(不会画图,不然轻松许多),是整体先将大的值向后移动,然后排序。
比如:1,3,2,6,5,4
先将1与3比较,发现1<3,到下一位,3与2比较,3向后移动一位…………(将最大的数移动到最后一位)
然后从第一次内循环出来,进行第二次比较。(第二大的值移动到倒数第二位)
…………最后由小到大排好序