目录
一.全局变量影响范围
类型一:
题1:
int x = 5, y = 7;
void swap()
{
int z;
z = x;
x = y;
y = z;
}
int main()
{
int x = 3, y = 8;
swap();
printf("%d,%d\n",x, y);
return 0;
}
解释
主函数内重新创建了与全局变量x、y变量名相同的局部变量x、y,swap函数中改变的x、y为全局变量,返回主函数后遵循局部有些原则,打印局部变量x、y
- 在函数内部创建与全局变量名相同的变量时,在该函数内调用该变量名,都是局部变量
题2:
//最后输出为
#include <stdio.h>
int i;
void prt()
{
for (i = 5; i < 8; i++)
printf("%c", '*');
printf("\t");
}
int main()
{
for (i = 5; i <= 8; i++)
prt();
return 0;
}
//答:***
解释:
变量i为全局变量,在函数体内未曾定义新的变量i时,使用的变量i为全局变量,在一个函数体内发生改变,其它函数体内相应改变
类型二:
//a、b、c、d那个是指针变量
#define INT_PTR int*
typedef int* int_ptr;
INT_PTR a, b;
int_ptr c, d;
//答:a、c、d
解释:
#define是宏定义,仅仅是直接替换,表示:int* a,b; 其中a是指针变量,b是整形变量。
typedef是将int*定义一个别名int_ptr, int_ptr c,d;中c,d都是int_ptr类型变量
二.转义字符
类型一:
//判断该数组定义是否正确
char c2[] = {'\x10','\xa','\8'};
//答:错误
解释:
\ddd ddd表示1到3个八进制数 如:\130 转义为 字符X
\xhh hh表示1到2位十六进制数 如:\x30 转义为 字符0
‘\8’中,\后的数字应该是一个八进制数0~7,而8不在其中,‘\8’此时表示两个字符,此写法错误
三.循环表达式
类型一:
t = 0;
while (printf("*"))
{
t++;
if (t < 3)
break
}
解释:
因为printf内有输出的元素,元素个数为1,printf函数的返回值为1,此循环恒位真
四.函数
类型一:
一个函数不写返回值类型,默认的返回值类型是int
解释:
不提倡不写返回值类型
类型二:
print(char* s)
{
if (*s)
{
print(++s);
printf("%c", *s);
}
}
int main()
{
char str[] = "Geneius";
print(str);
return 0;
}
//该程序最终输出为:suiene
解释:
第一次递归时,++s,此时*s的值已经是'e',返回第一次递归函数后,输出的是已经++的s地址内的值'e'
五.数组
类型一:
//数组num的大小是多少
int num['10'];
//答:12592
解释:
'10'在VS中转化为十进制的值为12592,代表字符’0‘,加减12592可以以’0‘为中心得到ASCII码值,但这这种写发是错误的
类型二:
//下面两个表达式为什么不于X[i][j]等效
*(X+i)[j];
*(X+i+j);
解释:
*(X+i)[j]:其中[]的优先级大于*,(X+i)先于[j]结合,此时(X+i)的类型为int[]*,于[j]结合错误
*(X+i+j):表示X[i+j]
类型三:
&a[0]++;
//写法错误
解释:
a[0]先与++结合,为一个表达式,无法取一个表达式的地址
六.操作符
类型一:
//最终输出结构为
int main()
{
int a = 1, b = 2, m = 0, n = 0, k;
k = (n = b < a) && (m = a);
printf("%d,%d\n", k, m);
return 0;
}
//答:0 0
解释:
首先,n=b<a中,关系运算符优先级高于赋值运算符,其中,b<a为假,n=0
所以,k=(n=b<a)&&(m=a)为k=(0)&&(m=a),
&&逻辑与前表达式为假,后面的表达式不会运行,k=0,m=0;
类型二:
int main()
{
int x = -1;
unsigned int y = 2;
if (x > y)
{
printf("x is greater");
}
else
{
printf("y is greater");
}
return 0;
}
//输出为:x is greater
解释:
int类型小于unsigned int,比较时会发生隐式类型转化,-1转化为unsigned int类型是一个很大的数,所以x>y正确
类型三:
double x = 1.42;
int a = x % 3;
//X%3是错误写法,%左右必须是整形
类型四:
题1:
void func()
{
int k = 1 ^ (1 << 31 >> 31);
printf("%d\n", k);
}
//最终输出为-2
解释:
1<<31后为0x80000000,即符号位为1,其它为0,向右移31位时,符号位为1,结果是0xFFFFFFFF,即-1,1^(-1)=-2
题2:
#include<stdio.h>
int main()
{
int n = 1001;
int ans = 0;
for (int i = 1; i <= n; ++i)
{
ans ^= i % 3;
}
printf("%d", ans);
return 0;
}
//输出为0
解释:
i%3的周期为3;其中:
i | ans |
1 | 1 |
2 | 3 |
0 | 3 |
1 | 2 |
2 | 0 |
0 | 0 |
ans的值每6次是一个循环,1001%6=5,最终i%3=2,2^2=0;
类型五:
#include <stdio.h>
int main()
{
int i = 1;
sizeof(i++);
printf("%d\n", i);
return 0;
}
//最后输出为1
解释:
sizeof是一个编译阶段就执行的运算符,其内的任何运算都不执行,只推测出变量的大小
类型六:
//一下那个操作可以使a的低四位翻转
a|0xF;
a&0xF;
a^0xF;
~a;
//答:a^0xF
解释:
0xF表示低四位全为1
a|0xF:最终结果低四位全为1
a&0xF:a的不同位为0时,a为0,为1时,a为1,a保持不变
a^0xF:相同为0,不同为1,a的不同位为1时,结果为0,为0时,结果为1
~a:表示a包括符号位按位取反,与题意不符
类型七:
//输入为1024
int fun(unsigned int x)
{
int n = 0;
while (x + 1)
{
n++;
x = x | (x + 1);
}
return n;
}
//最后输出为23
解释:
x=x|(x+1);的作用是每次循环把x的二进制中从右往左数的最后一位0变成1,直道变
成全1的时候x+1就溢出为全0,循环结束。
2014的二进制是0000 0000 000 0000 0000 0111 1101 1110,所以结果是23
七.指针
类型一:
//*pa的值为
float a[3]={1.5,2.5,3.5};
*pa=a;
*(pa++)*=3;
//*pa的值为2.5
解释:
pa++,为后置++,此时pa表示的地址仍然是a[0],该行程序运行完后,pa的地址为a[1]的地址,*pa的结果为2.5
类型二:
#include <stdio.h>
int main()
{
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }, * p = a + 5, * q = NULL;
*q = *(p + 5);
printf("%d %d\n", *p, *q);
return 0;
}
//程序运行后报错
解释:
指针变量q内运含的地址为空,无法对NULL地址包含的数据进行修改,*q=*(p+5);运行错误
类型三:
//初始化指针变量
int* a1=NULL;
int* a2=0;
//0和NULL是等价的
类型四:
struct T
{
char name[20];
int age;
int sex;
} a[5], *pa=a;
//判断此scanf是否正确
scanf("%d", pa->age);
//错误
解释:
pa->age表示的是变量,如果已经赋值,可以直接使用printf打印,但是scanf函数中,需要数组地址,从而赋值,无法对变量赋值