int main(int argc , char *argv[]) { unsigned char a = 255; char ch = 128; a -= ch; printf("a = %d ch = %dn", a, ch); }
结果:a = 127 ch = -128
`对a:先将a看作int,就是 0000 0000 0000 0000 0000 0000 1111 1111 ,然后截取char类型的长度,就是1111 1111(补码),因为无符号,原码:1111 1111,就是255,减去128得127。
对ch:char类型,8字节,128的原码就是1000 0000,这是个有符号型,所以输出,为-128.
2. 下面代码的运行输出结果是什么,并说说你的理解。int main(int argc, char *argv[]) { char *str = "Xi You Linux Group 20"; printf("%dn", printf(str)); return 0; }
结果:Xi You Linux Group 2021
printf("%d",printf(str)), 是输出printf(str)的返回值,printf(str)的返回值是printf(str)中输出的字节数,"Xi You Linux Group 20"正好21个字节,所以输出了21,。
3. 这段代码的输出结果是什么?为什么会出现这样的结果?
int i = 2; void func() { if(i != 0) { static int m = 0; int n = 0; n++; m++; printf("m = %d, n = %dn", m, n); i--; func(); }else{ return; } } int main(){ func(); return 0; }
这一题相同的类型,我以前的面试题分析写过了,就不过多写了,就是变量的生命周期和定义域的东西。
4. 下面程序会出现什么结果?为什么会出现这样的结果?int main(int argc, char * argv[]) { char ch = 'A'; int i = 65; unsigned int f = 33554433; *(int *)&f >>= 24; *(int *)&f = *(int *)&f + '?'; printf("ch = %c i = %c f = %cn", ch, i, *(int *)&f); return 0; }
对ch,ch直接输出A.
对i,A的ascii正好是65
对f,33554433>>24后为2,2+‘?’,?的ascii为63,加起来正好65;
这里的f强制换为int类型后在运算,输出,因为char是有符号型的.
5. 下面代码的运行输出结果是什么,并说说你的理解.
int main(int argc, char *argv[]) { int a[2][2]; printf("&a = %p t&a[0] = %p t&a[0][0] = %p n", &a, &a[0],&a[0][0]); printf("&a+1 = %p t&a[0]+1 = %p t&a[0][0]+1= %p n", &a+1,&a[0]+1, &a[0][0]+1); return 0; }
&a,%a[0],&a[0][0]指向的地址一样,都是数组的一个数的地址。
&a+1是在&a[0][0]的地址上增加sizeof(a)的长度,&a[0]+1是在&a[0][0]的地址上增加sizeof(a[0])的长度,&a[0][0]+1是在&a[0][0]的地址上增加sizeof(a[0][0])的长度.
运行结果:&a = 0x7ffe5aae4420 &a[0] = 0x7ffe5aae4420 &a[0][0] = 0x7ffe5aae4420
&a+1 = 0x7ffe5aae4430 &a[0]+1 = 0x7ffe5aae4428 &a[0][0]+1= 0x7ffe5aae4424
注意:你的运行结果可能和我不同,因为地址是使用时分配的,每次分配的可能不一样。
6. 下列程序的功能是什么?有什么问题,你能找出问题并解决它吗?int* get_array() { int array[1121]; for (int i = 0; i < sizeof(array) / sizeof(int); i++) { array[i] = i; } return array; } int main(int argc, char *argv[]) { int *p = get_array(); }
警告:函数返回局部变量的地址。(我还没看,编译器就自己报出来了)
函数不能返回局部变量的地址,因为,出了函数后地址中的值就会被抛弃,可能你调用完函数马上用不会有问题,但你在使用这个值和函数之间加一条占用地址的语句,就会出错。
对于这种情况,可以用static局部静态变量来解决,或者从主函数传入地址。
int* get_array() { static int array[1121]; for (int i = 0; i < sizeof(array) / sizeof(int); i++) { array[i] = i; } return array; } int main(int argc, char *argv[]) { int *p = get_array(); }
7. 下面代码的运行输出结果是什么,并说说你的理解。
int main(int argc, char *argv[]) { char str[] = "XiyouLinuxGroup"; char *p = str; char x[] = "XiyouLinuxGroupt106Fbamily"; printf("%zu %zu %zu %zun", sizeof(str), sizeof(p),sizeof(x), strlen(x)); return 0; }
结果:16 8 25 24
sizeof和strlen的区别:
sizeof 是C 语言的一种单目运算符,strlen是个函数.
sizeof以字节的形式给出 *** 作数的存储空间的大小,strlen 计算的是字符串的长度。
sizeof()的()中不能调用函数。
strlen是根据“”来判断是否结束的,所以strlen只能判断字符串.
指针64位下都是8字节,32位下4字节,strlen会计算上“”.
8. 如下程序,根据打印结果,你有什么思考?int add(int *x, int y) { return *x = (*x^y) + ((*x&y)<<1); } int a; int main(int argc, char *argv[]) { int b = 2020; if(add(&b, 1) || add(&a, 1)) { printf("XiyouLinuxGroup%dn", b); printf("Waiting for y%du!n", a); } if(add(&b, 1) && a++) { printf("XiyouLinuxGroup%dn", b); printf("Waiting for y%du!n", a); }
||是先判断左边的,如果为真就不再判断右边的,为假就判断右边的,只要有一个为真就为真。
&&是先判断左边的,如果为假就不判断右边的,否则就判断,只有两个都为真,才会是真。
9. 在下段程序中,我们可以通过第一步打印出 a 的地址,假如在你的机器上面打印结果 是 0x7ffd737c6db4;我们在第二步用 scanf 函数将这个地址值输入变量 c 中;第三 步,随机输入一个数字,请问最终输出了什么结果,你知道其中的原理吗?void func() { int a = 2020; unsigned long c; printf("%pn", &a); printf("我们想要修改的地址:"); scanf("%lx", &c); printf("请随便输入一个数字:"); scanf("%d", (int *)c); printf("a=%dn",a); }
a的值将会被修改,因为a这个变量指向的地址里的值被赋给了c,然后a和c指向了同一块地址,所以修改c的值,也会同步修改a的值,修改a的值也会影响c.
(第十题问c语言源程序到可执行文件的被我吃掉了)
11. 请解释一下这行代码做了什么?
puts((char*)(int const[]){ 0x6F796958,0x6E694C75,0x72477875, 0x3270756F,0x313230,0x00000A });
结果:XiyouLinuxGroup2021(小端)
大小端,16进制的ascii码,19年,20年都有。
12. 请随机输入一串字符串,你能解释一下输出结果吗?
int main(int argc, char *argv[]) { char str[1121]; int key; char t; fgets(str, 1121, stdin); for(int i = 0; i < strlen(str) - 1; i++) { key = i; for(int j = i + 1; j < strlen(str); j++) { if(str[key] > str[j]) { key = j; } } t = str[key]; str[key] = str[i]; str[i] = t; } puts(str); return 0; }
这是字符串利用ascii码进行排序,按ascii码由小到大排序;
13. 用循环和递归求 Fibonacci 数列,你觉得这两种方式那种更好?说说你的看法。如果 让你求 Fibonacci 数列的第 100 项,你觉得还可以用常规的方法求解吗?请试着求 出前 100 项的值(tip 大数运算)。
我先忙猜循环,因为递归调用函数,会极大影响效率,(C++中inline函数改善了这种情况)
然后就是写代码分析了:
long recursive(int n){ if(n==1||n==2){ return 1; }else{ return recursive(n-1)+recursive(n-2); } } long loop(int n){ if(n == 1 || n == 2) return 1; long a = 1, b = 1, temp; int i; for(i = 3; i <= n; i++) { temp = b; b = a + b; a = temp; } return b; } int main(){ int a=10; scanf("%d",&a); long int c=recursive(a); printf("%ldn",c); long int b=loop(a); printf("%ldn",b); return 0; }
可以看出,递归的时间复杂度是O(2^n),循环的则是O(n),可以看出循环的效率远高出递归。
对于第100个斐波那契数,长度超出 long long,只能用大数计数:
( 前几天刚看的求第1000位数,改一下正好能求第100个的值):
int main(){ int fib[3][1005]={{0,0},{1,1},{1,1}};//三个斐波那契数:f(n),f(n-1),f(n-2),各一维数组第一个位为位数计数。 int n=2;//n为第n位斐波那契数 while (n < 100) { n += 1; for(int i=1;i <= fib[(n - 1) % 3][0];i++){ fib[n%3][i]=fib[(n-1)%3][i]+fib[(n-2)%3][i];// 对应位置上的数字相加 } fib[n%3][0]=fib[(n-1)%3][0];//将位数及时移动过来 for (int i = 1; i <= fib[n % 3][0]; ++i) { //处理进位 if (fib[n % 3][i] < 10) continue; fib[n % 3][i + 1] += fib[n % 3][i] / 10; fib[n % 3][i] %= 10; fib[n % 3][0] += (i == fib[n % 3][0]); } } for(int i=1;i<=fib[n % 3][0];i++){ printf("%d",fib[n%3][i]); } printf("n"); }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)