C语言夺命十题?

题目涉及部分内容:

  1. 结构体与结构体指针
  2. 指针,数组
  3. 宏定义与指针函数
  4. 函数
  5. 字符串数组
  6. 可变长参数函数

  1. 程序的输出是什么?
#include <stdio.h>
#include <setjmp.h>
#include <conio.h>
#include <stdlib.h>
int main(){
	volatile int b = 3;
	if(setjmp(buf) != 0){
		printf("%d\n",b);
		system("pause");
		exit(0);
	}
	b = 5;
	longjmp(buf,1);
	system("pause");
	return 0;
}

结果:5
setjmp函数存储“非本地goto”的上下文信息,返回0。该longjmp函数将控制转移到已setjmp初始化的调用buf,并且从这一点继续执行,就好像setjmp返回了1

【注意】:之后被修改的非易失性自动变量setjmp变得不确定longjmp。没有volatile限定词,这个程序的行为将是不确定的。这个规则允许更好的代码优化。


  1. 程序的输出是什么?
int main(){
	struct node {
		int a;
		int b;
		int c;
	}
	struct node s = {3,5,6};
	struct node *pt = &s;
	
	printf("%d\n",*(int*)pt);
	system("pause");
	return 0;
}

结果:3
结构体成员按顺序排列在内存中。指针强制类型转换为其中某个成员的类型,即指向了结构体中的一个成员,提领之后为该结构体成员变量的值。


  1. 程序的输出是什么?
int main(){
	int a[5] = {1,2,3,4,5};
	int *ptr = (int*)(&a + 1);
	printf("%d %d\n,*(a+1),*(ptr-1));
	system("pause");
	return 0;
}

结果:2 5
数组a为拥有5个元素的整型,对变量名加减隐式退化为对指针的操作,a+1访问到了数组下标为1的元素。
&a就有成为了一个数组指针。因此&a + 1产生的指针越过了一个5个数组元素大小的数组,刚好跳过了a数组。此时对此指向的ptr指针进行强制类型转换,它现在的“步距”相当于一个数组成员,使ptr减一指向正好回到了a数组的最后一个元素。

【注意】:一般来说,不能使用非空指针的值不指向有效的对象。但是,指向数组末尾的指针是一个例外。这使ptr合法的初始化,即使它不能被解除引用。


  1. 程序的输出是什么?
void foo(int [][3]);
int main(){
	int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
	foo(a);
	printf("%d\n",a[2][1]);
	system("pause");
	return 0;
}
void foo(int b[][3]){	
	++b;
	b[1][1] = 9;
}	

结果:9
在中foo,b有指向数组[3]的类型指针int,并在增量后指向数组a[1]()。所以b[1]有类型数组[3] int,它表示数组a[2]()。在值上下文中,b[1]“decay”成一个指向a[2][0](7)的指针,所以b[1][1]表示a[2][1],其值从8变为9


  1. 程序的输出是什么?
int main(){
	int a,b,c,d;
	a = 3;
	b = 5;
	c = a,b;
	d = (a,b);
	printf("c = %d ",c);
	printf("d = %d\n",d);
	system("pause");
	return 0;
}

结果:c=3 d=5
逗号运算符(逗号表达式)评估两个操作数并生成第二个值。它的优先级低于赋值。因此c = a, b相当于c = a,而d = (a, b)相当于d = b


  1. 程序的输出是什么?
#include <stdarg.h>
int ripple(int n,...){
	int i,j,k;
	va_list p;
	k = 0;
	j = 1;
	va_start(p,n);
	for(;j < n;++j){
		i = va_arg(p,int);
		for(;i;i &= i - 1){
			++k;
		}
	}
	va_end(p);
	return k;
}
int main(){
	printf("%d\n",ripple(3,5,7));
	return 0;
}

结果:5
va_arg宏产生的“传递参数…”一个可变参数函数的一部分。在ripple它将被调用两次,i首先设置为5,然后到7
表达式i &= i - 1重置最右边的1i。例如,如果i6(二进制110),i & i - 1则是4(二进制100)。内部for循环执行到i0,所以k增加了1位的数量i
5(二进制101)和二进制111(二进制)中有两个1位,所以ripple返回5


  1. 程序的输出是什么?
void f(char**);
int main(){
	char *argv[] = {"ab", "cd", "ef"r "gh", "ij", "kl"};
	f(argv);
    return O;
}
void f (char **p){
	char *t;
	t =(p += sizeof (int)) [-1] ;
	printf("%s\n", t) ;
}

结果:cd
fp最初指向指针数组中的第一个char*"ab"argv。添加sizeof(int)= 2p使其指向第三个char*"ef"),之后p[-1]表示第二个char*"cd")。


  1. temp是什么类型?
typedef int(*test)(float *,float *);
test temp;

结果:指向函数的指针(取两个指针float参数并返回int
typedef声明为一个类型创建一个同义词,然后可以用它来声明该类型的对象。注意这个类型的新名字出现在一个变量名的位置上,好像你正在声明一个变量。与#define指令的语法相比,这可以使其看起来倒退。


  1. 程序的输出是什么?
void e(int);
int main(){
	int a = 3;
	e(a);
	putchar('\n');
	return 0;
}
void e(int n){
	if(n > 0){
		e(--n);
		printf("%d ",n);
		e(--n);
	}
}

结果:0 1 2 0
在伪代码中:
e(0), e(-1) -> {}
e(1) -> -> {{}, print 0, {}} ->
e(2) -> -> {, print 1, {}} ->
e(3) -> -> {, print 2, } ->


  1. 程序的输出是什么?
int main(){
	int a[][3] = {1,2,3,4,5,6};
	int (*ptr)[3] = a;
	printf("%d %d ",(*ptr)[1],(*ptr)[2]);
	++ptr;
	printf("%d %d ",(*ptr)[1],(*ptr)[2]);
	sysetm("pause");
	return 0;
}

结果:2 3 5 6
a有数组[3]的类型,数组[2] intptr最初指向第一个数组[3]()。增量后,它指向第二个数组[3]()。当然,*ptr表示ptr正好指向的数组[3]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

giturtle

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值