1.分析以下代码段,并解释输出结果和原因
int main(int argc,char *argv[])
{
int nums[3][3] = {1,2,3,4,5,6,7,8,9};
printf("%d\n",nums[1][-2]);
printf("%d\n",(-1)[nums][5]);
printf("%d\n",-1[nums][5]);
return 0;
}
输出结果为2,3,-9。
第一个nums[1][-2]=nums[1*3-2]=nums[1]=2(将其看为一维数组);
第二个(-1)[nums][5]=nums[-1][5]=nums[-1*3+5]=nums[2]=3(将其看为一维数组);
第三个-1[nums][5]=-1nums[1][5]=-1nums[1*3+5]=-1nums[8]=-9(将其看为一维数组)。
2.分析以下代码段,给出输出结果,并给出自己的理解。
int main()
{
int a[3][2] = {2,0,1,8};
char *str = (char *)malloc(sizeof(char)*20);
strcpy(str,"\0101\\xb2");
printf("%zu\n",sizeof(a));
printf("%zu %d\n",sizeof(a[1][1] = 0),a[1][1]);
printf("%d\n",a[1][1]);
return 0;
}
输出结果是24 4 8 8。a的大小为6个int的大小所以sizeof(a)=6*4=24;a[1][1]为int类型所以sizeof(a[1][1])为4(sizeof只关心类型不会完成表达式的运算,所以a[1][1]仍是8);
3.参考所给代码,简要地谈一谈你对 static 关键字的理解。
static int a = 2018;
static void func(void)
{
static int b;
printf("a = %d, b = %d\n", a++, ++b);
}
int main(int argc, char *argv[])
{
func( );
func( );
func( );
return 0;
}
静态全局变量:静态全局变量只在定义该变量的源文件内有效。
静态局部变量:静态局部变量只能初始化一次,之后无论发生怎样的变化,依旧是初始时的结果。
静态函数:静态函数在内存中只有一份,而非静态函数在每次被调用时都会拷贝一次。
4.请说明C语言程序从源代码到形成可执行文件的过程,
1.预处理:经过预处理,会产生一个没有宏定义,没有条件编译指令,没有特殊符号的输出文件,这个文件的含义同原本的文件无异,只是内容上有所不同。
2.编译:将预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后,产生相应的汇编代码文件。
3.汇编:将编译完的汇编代码文件翻译成机器指令,并生成可重定位目标程序的.o文件,该文件为二进制文件,字节编码是机器指令。
4.链接:通过链接器将一个个目标文件(或许还会有库文件)链接在一起生成一个完整的可执行程序。
5.根据所给代码,说明 const 关键字的用法,指出标号为 (1)~(4) 的 代码哪些是错误的。
char y[ ] = "XiyouLinuxGroup", x[ ] = "2018";
char *const p1 = y; const char *p2 = y;
/* (1) */ p1 = x;
/* (2) */ p2 = x;
/* (3) */ *p1 = 'x';
/* (4) */ *p2 = 'x';
char *const p1是指针常量,不能修改其指向的地址所以(1)错误。
const char *p2是常量指针,不能修改地址上的内容所以(4)错误。
6.猜想下面程序的输出,并谈谈自己的理解。
int main(int argc, char *argv[])
{
int a[5];
printf("%p\n", a);
printf("%p\n", a+1);
printf("%p\n", &a);
printf("%p\n", &a+1);
return 0;
}
输出结果:
000000000062FE00
000000000062FE04
000000000062FE00
000000000062FE14
第一个代表数组的地址;
第二个代表a[1]的地址;
第三个代表数组地地址;
第四个代表a[0]再加上整个数组大小的地址。
7.谈谈你对 main 函数的理解,可以从参数、返回值等角度分析。 int main(int argc, char *argv[]){/*…*/}
mian函数是主函数,所以程序始于mian函数终于main函数,main函数可以调用任意函数,而其它函数不可调用main函数。
argc:代表参数的个数。argv[]:是一个指针类型的字符数组,其中每一个元素指向一个字符串。argv[0]:指向程序的路径名,argv[…]:指向第n个参数所对应的字符串。
8.分析以下函数,给出 f(2018) 的值,推测并验证函数的作用。
int f(unsigned int num);
{
for (unsigned int i = 0; num; i++){
num &= (num – 1);
}
return i;
}
f(2018) 的值为7。
该函数的作用是计算一个数其二进制中1的个数。
9.分析以下代码段,解释输出的结果。
int main(int argc, char *argv[])
{
char n[] = { 1, 0, 0, 0 };
printf("%d\n", *(int *)n);
}
输出结果为1,int *是一个类型的强转换所以*(int *)n就是int[0] =1。
10.分析以下代码段,解释输出的结果。
#define YEAR 2018
#define LEVELONE(x) "xiyoulinux"#x"\n"
#define LEVELTWO(x) LEVELONE(x)
#define MULTIPLY(x,y) x*y
int main(int argc, char *argv[])
{
int x = MULTIPLY(1+2,3);
printf("%d\n",x);
printf(LEVELONE(YEAR));
printf(LEVETWO(YEAR));
}
输出结果为:
7
XiyouLinux YEAR
XiyouLinux 2018
define只做替换并不进行运算;define 可以将其后的参数字符串化。
11.以下代码段输出的两个值相等吗?为什么?
struct icd {
int a;
char b;
double c;
};
struct cdi {
char a;
double b;
int c;
};
int main(int argc, char *argv[])
{
printf("%zu %zu\n",sizeof(struct icd),sizeof(struct cdi));
}
输出结果16 24,因为在对结构体申请内存空间时需遵循字节对齐原则。