西安邮电大学Liunx兴趣小组2021——2023面试题又长又臭版
2021年面试题
-
大小和长度竟然不是一个意思
-
sizeof()和strlen()异同
-
他们对于不同参数的结果有什么不同
-
int main(void)
{
char s[] = "I love linux\0\0\0";
int a = sizeof(s);
int b = strlen(s);
printf("%d %d\n",a,b);
}
嗯嗯,首先关于sizeof和strlen的区别:sizeof返回的结果是对象的大小,所以输出中的a的大小就应该是s的大小(不会有人觉得大小是15吧,注意字符串后面会补‘\0’);
然后是strlen,它返回的是字符串的长度,但是!这个长度统计到’\0‘就结束了,并且不包括‘\0’,切记切记。
2. 箱子的大小和装入物品的顺序有关
- 两个结构体的大小是否相等呢?
struct test1
{
int a;
short b;
double c;
};
struct test2
{
short b;
int a;
double c;
}
int main(void)
{
struct test1 t1;
struct test1 t2;
printf("sizeof(t1): %d\n", sizeof(t1));
printf("sizeof(t1): %d\n", sizeof(t2));
}
首先这两个结构体的大小是相等的(题目根本吓不到我)!!!这题考的内容是内存对齐,这两结构体的内存如下图
- 哦,又是函数
- 编写一个用来输出二维数组的函数
//在这补全函数
int main(void)
{
int arr[10][13];
for(int i = 0;i < 10;i++)
{
for(int j = 0;j < 13;j++)
{
arr[i][j] = rand(); //rand()函数用来生成伪随机数
}
func(arr);
}
}
答案:“你真的看不见我吗”!
直接上代码
func(int arr[10][13]) //因为上面把数组的大小已经定义了,所以直接写
{
for(int i = 0;i < 10;i++)
{
for(int j = 0;j < 13;j++)
{
printf("%d ",arr[i][j]);
}
}
}
- 就不能换个变量名吗
- 谈谈传值和传址的区别
- 对生命周期的理解
int ver = 123;
void func1(int ver)
{
ver++;
printf("ver = %d\n",ver);
}
void func2(int *pr)
{
*pr = 1234;
printf("*pr = %d\n",*pr);
pr = 5678;
printf("ver = %d\n",ver);
}
int main()
{
int a = 0;
int ver = 1025;
for(int a = 3;a < 4;a++)
{
static int a = 5;
printf("a = %d\n",a);
a = ver;
func1(ver);
int ver = 7;
printf("ver = %d\n",ver);
func2(&ver);
}
printf("a = %d\tver = %d\n",a ,ver);
}
运行结果如下
a = 5
ver = 1026
ver = 7
*pr = 1234
ver = 123
a = 0 ver = 1025
我们就从结果来看:对于第一个a=5,在for循环里声明的a会把循环条件那的a给“屏蔽”掉,所以第一个输出a的值为5,还要注意的是循环里的a是静态变量,具有文件作用域(也即是它的生命周期和程序一样长,只有在程序结束时才被释放);
然后是第一个ver值,同理a,它输出main函数里声明的ver;而后循环里又声明一个ver且值被赋予7,即第二个ver输出,注意这里并不是对ver重赋值,从中也可以看出局部变量的屏蔽作用也只有在被声明后才行;对于*pr的值是很好理解的,先对指针解引用再赋值;第三个ver的值就不那么对劲了,不是已经屏蔽掉高一级变量了吗?其实这里有个坑,在调用这个函数的时候,如果没有给它传对应参数,它就会默认调用全局变量,举个栗子
int a = 123;
void func1()
{
printf("%d",a);
}
void func2(int a)
{
printf("%d",a);
}
void func3(int *p)
{
printf("%d",a);
}
int main(void)
{
int a = 1;
func1(); //结果为123
func2(a); //结果为1
func3(&a); //结果为123
}
回到前面,在摆脱掉for循环的块后,a和ver的值就变成main开头声明的值了。那么传值和传址的区别呢?我们知道函数在结束后就会把前面拷贝的数据释放掉,对于传值,最后拷贝变量被释放,所以函数过后其值并不会改变;对于传址,最后释放的是指向变量的地址,而值没被释放,所以函数结束后值会改变。对于生命周期通俗点讲就是变量能活多久
- 套娃真好玩
- 说明下面函数如何求和
unsigned sum(unsigned n)
{
return n ? sum(n - 1) + n : 0;
}
int main(void)
{
printf("%u\n", sum(100));
}
其实就是函数的递归啦。我们直接倒过来看,最后一次函数的调用n等于0,然后退到上一层返回的sum(n-1)+n中的sum()就是0,然后加上n即为1,再返回上一层,sum()为1(前一层的结果就是后一层的sum()值),加上n为2等于3,然后重复这个过程就实现了相加啦。
- 算不对的算术
void func(void)
{
short a = -2;
unsigned int b = 1;
b += a;
int c = -1;
unsigned short d = c*256;
c <<=4;
int e = 2;
e = ~e | 6;
d = (d & 0xff) + 0x2022;
printf("a=0x%hhx\t\nb=0x%hhx\t\nd=0x%hhx\t\ne=0x%hhx\t\n",a,b,d,e);
printf("a=0x%hhx\t\n",(signed char)c);
}
b+a等于-1,但b是无符号类型,所以会发生下溢,所以b会等于unsigned int最大值端开始减少,d也同理。然后是位运算,请大家自行查看
d

e

- 指针和数组的恩怨情仇
int main(void)
{
int a[3][3] = {{1, 2, 3},{4, 5, 6},{7, 8, 9}};
int(*b)[3] = a;
++b;
b[1][1] = 10;
int *ptr = (int *)(&a + 1);
printf("%d %d %d\n",a[2][1],**(a+1),*(ptr-1));
}
首先b是一个指向3个int大小的指针(区别*b[3]),对b加1,实际上实现了3个int的跨越,然后把数组第一排第一列的数赋值为10,最后对二维数组取址,此时它说指向的地址是整个二维数组,所以加1后直接跨过了整个数组,所以ptr指向该数组的下一个地址,那么ptr-1(区别前面数组取址所指的“地址块”大小)后就指向数组最后一个了,至于双重解引用就没什么好说的。
- 移形换位之术
- 使用值或地址调用a,b, c是否正确
- 找出语法错误
- const int和int const是否有区别
- const int和int const是否有区别
int a = 1;
int const b = 2; //不能变
const int c = 3; //不能变
void func0(int n)
{
n += 1;
n = a;
}
void func1(int *n)
{
*n += 1;
n = &a;
}
void func2(const int *n)
{
*n += 1; //不能变
n = &a;
}
void func3(int *const n)
{
*n += 1; //不能变
n = &a;
}
void func4(const int *const n)
{
*n += 1; //不能变
n = &a; //不能变
}
实际上const int和int const并没有什么区别,但对于指针就不一样了
const int*指向的变量可以改变但指向不能改变
int *const指向可已改变但指向的值不能变
const int *const两者皆不能改变
- 听说翻转字母大小不影响英文的阅读
- 编写转换字母大小写,并返回字符串的函数 convert
char *convert(const char *s);
int main(void)
{
char *str = "XiyouLinux Group 2022";
char *temp = convert(str);
puts(temp);
}
废话不多说,上代码
char *convert(const char *s);
int main(void)
{
char *str = "XiyouLinux Group 2022";
char *temp = convert(str);
puts(temp);
free(temp); //因为用了分配内存,所以需要释放
}
char *convert(const char *s)
{
int lenth = strlen(s);
char *gets =(char *)malloc(sizeof(s));
strcpy(gets,s);
for(int i=0;i<lenth;i++)
{
if(gets[i]<='Z'&&gets[i]>='A')
{
gets[i] += (char)32;
}
else if(gets[i]<='z'&&gets[i]>='a')
{
gets[i] -= (char)32;
}
}
return gets;
}
- 交换礼物的方式
- 锐评一下下面三个swap
- do while(0)作用
- 其他实现swap方法
#define Swap1(a, b, t)\
do \
{ \
t = a; \ //记得加
a = b; \
b = t; \
}while (0) \
#define Swap2(a, b) \
do \
{ \
int t = a; \
a = b; \
b = t; \
}while (0) \
void Swap3(int a,int b)
{
int t = a;
a = b;
b = t;
}
使用#define调换的数是可以保存的而函数方式不会
主要看看第二问,我们都知道define是对内容的“替换”,在有多行替换的时候就可能出问题,比如这样
#define Swap(a,b) \
int t = a;\
a = b; \
b = t; \
int main(void)
{
int a,b;
scanf("%d %d",&a,&b);
if(a>b)
Swap(a,b);
}
我们本来是想如果a>b才换,可实际上因为if只管一行,就会出大问题,而使用do while(0)就不存在这个问题
其他实现swap方法(乱写的啊)
a = a+b;
b = a-b;
a = a-b;
- 据说有个东西叫参数
- argc和argv的含义
- 在不使用argc的情况下遍历argv
int main(int argc,char *argv[])
{
printf("argc = %d\n",argc);
for(int i =0;i < argc;i++)
printf("%s\n", argv[i]);
}
argc的值为我们在命令行中调用的参数的个数,argv则记录了这些参数,值得一提的是调用文件本身也是一个参数,所以argc的值最少也为一。
- 人去楼空
- 代码是否有误,谈谈静态变量
int *func1(void)
{
static int n=0;
n = 1;
return &n;
}
int *func2(void)
{
int *p = (int *)malloc(sizeof(int));
*p = 3;
return p;
}
int *func3(void)
{
int n = 4;
return &n;
}
int main(void)
{
*func1() = 4;
*func2() = 5;
*func3() = 6;
}
关于静态变量不必多说,主要看看程序,如果运行程序,会在func3出问题,原因是局部变量会随此函数一起被释放,其地址指向的内容不明,是不被允许的,相反的静态变量因为储存在静态区,不会和函数一起释放,所以是可以的。
- 奇怪的输出
int main(void)
{
int date[]={0x636c6557, 0x20656d6f, 0x78206f74, 0x756f7969, 0x6e694c20, 0x67207875,0x70756f72,0x32303220,0x00000a31};
puts((const char *)data);
}
这题的知识点是大小端储存(第一次看到的时候直接懵逼)关于大小端储存是什么,我从万能的网络粘来了:
大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,存储模式类似把数据当作字符串顺序处理。
小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,存储模式将地址的高低和数据位权有效地结合起来。
(我们平常用的笔记本是小端储存)
好多好难写(哭)
2022年面试题
- 我的计算器坏了?!
- 210000对应十进制是多少位
一道简单数学题,设它为k位数,则10k+1>210000>10k
再取 l g lg lg就可以判断了
1. printf还能这么玩
- 解释程序输出
int main(void)
{
if((3 + 2 < 2)>(3 + 2 > 2))
printf("Welcome to Xiyou Linux Group\n");
else
printf("%d\n",printf("Xiyou Linux Group - 2%d", printf("")));
}
首先是判断,先是判断2>2,不满足表达式值为0,再进行加法后判断,肯定是不满足的啦,所有执行else,然后是printf的嵌套,printf的返回值为它输出内容的长度,对于嵌套是由内往外执行的,就ok了。
- 你好你好你好呀
- 尝试解释程序输出
- 谈谈对sizeof和strlen的理解
int main(void)
{
char p0[] = "Hello Linux";
char *p1 = "Hello Linux";
char p2[11] = "Hello Linux";
printf("p0 == p1: %d, strcmp(p0, p2): %d\n", p0 == p1,strcmp(p0,p2));
printf("sizeof(p0): %zu, sizeof(p1): %zu, sizeof(*p2): %zu\n",sizeof(p0), sizeof(p1), sizeof(*p2));
printf("strlen(p0): %zu, strlen(p1): %zu\n",strlen(p0), strlen(p1));
}
字符串的比对就是从左到右按asc码比对字符,只有一一对应才相等,否则第一个不等字符谁编码大则对应字符串就大。strcmp是包含在string.h头文件的函数,用于比对字符串大小,相等返回0,若第一个参数小于第二个,则返回负数(asc码之差),反之返回正数。p0和p1都是代表了地址,而两者的地址肯定不相同,故p0 == p1等于0,p2因数组大小没有’\0’,所以p0比p2返回-72,p0大小为12('\0’别漏),p2指向字符串第一个字符的地址,解引用后大小为1,p1是指针为8。
- 换个变量名不行吗*
int a = 3;
void test()
{
int a = 1;
a += 1;
{
int a = a + 1;
printf("a = %d\n", a);
}
printf("a = %d\n", a);
}
int main(void)
{
test();
printf("a = %d\n", a);
}
第一个打印a会有‘a’ is used uninitialized的警告,a的值不能确定,视不同情况而定。
- 内存对不齐
- union和struct各自特点和他们的内存分配
typedef union
{
long l;
int i[5];
char c;
}UNION;
typedef struct
{
int like;
UNION coin;
double collect;
}STRUCT;
int main(void)
{
printf("sizeof(UNION) = %zu\n",sizeof(UNION));
printf("sizeof(struct) = %zu\n",sizeof(struct));
}
union共用一块内存其内存大小1为最大成员值,union和struct都要内存对齐
如下图


- Bitwize
- 用yong纸笔写出推导结果
- 对位运算的理解
int main(void)
{
unsigned char a = 4|7;
a<<=3;
unsigned char b = 5&7;
unsigned char c = 6^7;
c = ~c;
unsigned short d = (a ^ c)<< 3;
signed char e = -63;
e <<= 2;
printf("a: %d, b: %d, c :%d, d: %d\n",a,b,c, (char)d);
printf("e: %#x\n", e);
}
其实就是基本的位运算,只是要注意d转char类型只保留8位,因为char只有8位





- 英译汉
const作用
- char *const p;
- char const *p;
- const char *p;
int const* 是指向 const int 的指针
int *const 是指向 int 的 const 指针
const int const* 是指向 const int 的 const 指针
- 英译汉
- 含有10个指向int的指针的数组
- 指向含有10个int数组的指针
- 含有3个指向函数的指针的数组,被指向的函数有1个int参数并返回int
int *p[10];
int (*p)[10];
int (*p[3])(int);
- 混乱中建立秩序
- 谈谈排序算法
- 排序算法的思想,稳定性,时间复杂度,空间复杂度
冒泡
void BubbleSort(int array[], int n)
{
int i, j, k;
for(i=0; i<n-1; i++)
for(j=0; j<n-1-i; j++)
{
if(array[j]>array[j+1])
{
k=array[j];
array[j]=array[j+1];
array[j+1]=k;
}
}
}
- 手脑并用
- 实现ConvertAndMerge:输入两个字符并拼接,并翻转新字符串字母的大小写
- 提示:你需要为字符串分配内存
char *ConvertAndMerge(/*补全签名*/);
int main(void)
{
char words[2][20] = {"Welcome to Xiyou",{"Linux Group 2022"}}
printf("%s\n",word[0]);
printf("%s\n",word[1]);
ConvertAndMerge(word);
printf("str = %s\n",str);
free(str);
}
代码如下
char *ConvertAndMerge(char s[2][20])
{
char *gets =(char *)malloc(sizeof(s));
sprintf(gets,"%s%s",s[0],s[1]);
int lenth = strlen(gets);
for(int i=0;i<lenth;i++)
{
if(gets[i]<='Z'&&gets[i]>='A')
{
gets[i] += (char)32;
}
else if(gets[i]<='z'&&gets[i]>='a')
{
gets[i] -= (char)32;
}
}
return gets;
}
- 给你我的指针,访问我的心声
- 程序输出有些奇怪,请尝试解释一下程序输出
int main(int argc, char **argv)
{
int arr[5][5];
int a = 0;
for(int i = 0;i < 5;i++)
{
int *temp = *(arr + i);
for(int j = 0;i < 5;j++)
{
*temp = a++;
}
}
for(int i = 0;i < 5;i++)
{
for(int j = 0;j < 5;j++)
{
printf("%d\t",arr[i][j]);
}
}
}
先看结果
0 1 2 3 4 25 26 27 28 29 45 46 47 48 49 60 61 62 63 6470 71 72 73 74
为啥呢?第一次循环temp指到arr[0],然后循环从arr[0][0]的值由0到24,最后a=25,然后第二次循环temp指到arr[1],再开始循环,从arr[1][0]开始赋值,由25到44,此时a=45,循环依次进行就得到了输出。
- 奇怪的参数
- 你了解argc和argv
- 直接运行argc为什么值是1
- 程序会死循环吗
int main(int argc,char **argv)
{
printf("argc = %d\n", argc);
while(1)
{
argc++;
if(argc < 0)
{
printf("%s\n", char( *)argv[0])
break;
}
}
}
前两问直接粘贴:argc的值为我们在命令行中调用的参数的个数,argv则记录了这些参数,值得一提的是调用文件本身也是一个参数,所以argc的值最少也为一。
关于循环,并不会出现死循环,我们知道数据的存储有溢出的情况,argc一直增加到上界,发生上溢然后从下界开始向上增到0结束循环
- 奇怪的字符
- 程序的输出有点奇怪,解释一下输出
int main(int argc,char**argv)
{
int data1[2][3] = {{0x636c6557,0x20656d6f,0x58206f74},{0x756f7969,0x6e694c20,0x00000000}}
int data2[] = {{0x47207875,0x70756f72,0x32303220,0x00000a32}};
char *a = (char *)data1;
char *b = (char *)data2;
char buf[1024];
strcpy(buf, a);
strcpy(buf, b);
printf("%s\n", buf);
}
大小端储存请参考2021年面试题
- 小试牛刀
- 请谈谈对#define的理解
- 解释程序输出
#define SWAP(a, b, t) t = a;a = b; b = t
#define SQUARE(a) a * a
#define SWAPWHEN(a, b, t, cond) if(cond) SWAP(a, b, t)
int main()
{
int tmp;
int x = 1;
int y = 2;
int z = 3;
int w = 3;
SWAP(x, y, tmp);
printf("x = %d, y = %d, tmp = %d\n", x, y, tmp);
if(x > y) SWAP(x, y, tmp);
printf("x = %d, y = %d, tmp = %d\n", x, y, tmp);
SWAPWHEN(x, y, tmp, SQUARE(1 + 2 + z++ + ++w) == 100);
printf("x = %d, y = %d, tmp = %d\n", x, y, tmp);
printf("z = %d, w = %d, tmp = %d\n", z, w, tmp);
}
结果如下
x = 2, y = 1, tmp = 1
x = 1, y = 2, tmp = 2
x = 2, y = 2, tmp = 2
z = 5, w = 5, tmp = 2
我们主要看看第三个输出的SQUARE,进行代替后就成了
1 + 2 + z++ + ++w * 1 + 2 + z++ + ++w == 100
然后是SWAPWHEN,if语句只包含了一条语句即:
if(rand) t=a
其余的a = b;b = t都不属于if的语块内。
写不完,根本写不完(悲)
2023面试题
- 鼠鼠我呀,要被祸害了
- 有1000瓶水,其中一瓶有毒,小白鼠只尝一点带水的毒,24小时后就会准时死亡,
至少需要多少只小白鼠才能在24小时内鉴别出哪瓶水有毒?
我们使用译码器法,将1000瓶水用二进制编号,再将这1000瓶水按某一位是否为1分为10组(1000按二进制编号有10位,所以分10组)如第一组都是二进制编号第一位为1的水瓶的水,然后让10只小鼠喝下,若老鼠死亡,那么毒水的编号这一位就为1,反之为0,就可以找出来啦。
- 先预测一下~
- 按照函数要求输出自己的姓名试试~
char *welcome()
{
//请返回自己的姓名
}
int main(void)
{
char *a = welcome();
printf("Hi, 我相信 %s 可以面试成功!\n", a);
return 0;
}
char *welcome()
{
char *name="翠花";
return name;
}
int main(void)
{
char *a = welcome();
printf("Hi, 我相信 %s 可以面试成功!\n", a);
return 0;
}
最后函数释放的是地址,而字符串内容在常量区,没有被释放。(友情提示,还可以分配内存来实现)
- 欢迎来到Linux兴趣小组
- 有趣的输出,为什么会变成这样子呢~
int main(void)
{
char *ptr0 = "Welcome to Xiyou Linux!";
char ptr1[] = "Welcome to Xiyou Linux!";
if(*ptr0 == *ptr1)
{
printf("%d\n",printf("Hello, Linux Group - 2%d", printf("")));
}
int diff = ptr0 - ptr1;
printf("Pointer Difference: %d\n", diff);
}
printf的嵌套已经不想多说,只是注意ptr0和ptr1虽然相等,但地址不同
- 一切都翻倍了吗?
- 请解释一下程序的输出
- 请谈谈对sizeof和strlen
- 什么是sprintf(),它的返回值是什么
int main(void)
{
char arr[] = {'L', 'i', 'n', 'u', 'x', '\0', '!'},str[20];
short num = 520;
int num2 = 1314;
printf("%zu\t%zu\t%zu\n",sizeof(*&arr), sizeof(arr + 0),sizeof(num = num2 + 4));
printf("%d\n",sprintf(str,"0x%x",num) == num);
printf("%zu\t%zu\n", strlen(&str[0] + 1), strlen(arr + 0));
}
结果如下:
7 8 2
0
4 5
对数组名取址再解引用,结果还是数组本身,大小就为数组大小,和对数组名取大小一样,但数组名加0可不是这么回事,此时它代表的是地址,所以为8。然后还需注意sizeof是运算符,不是函数,所以sizeof里执行内容不会被保留,所以到最后num的值都是520,因为num是short类型,所以值为2。sprintf的返回值和它兄弟printf一样,都是打印长度。最后我们知道数组名也代表着数组的首地址,那么对数组首元素取址,就等价于数组名本身,再加1,地址右移1个,故长度为4,arr+0同理。
- 奇怪的输出
- 程序的输出结果是什么样的,请解释一下结果
int main(void)
{
char a = 64 & 127;
char b = 64 ^ 127;
char c = -64 >> 6;
char ch = a + b - c;
printf("a = %d b = %d c = %d\n",a, b, c);
printf("ch = %d\n", ch);
}
运算如下:

- 乍一看就不想看的函数
- 这个func()函数的功能是什么,怎么实现的?
int func(int a, int b)
{
if(!a) return b;
return func((a & b) << 1, a^b);
}
int main(void)
{
int a = 4, b = 9, c = -7;
printf("%d\n", func(a, func(b, c)));
}
我们知道&只有在都为1的情况下才为1,那么我们就可以用这个特性来表示进位,此时只需把结果右移一位就可以达到效果,^是在两个不相等的情况下才为1,否则为0,我们可以借此来表示不进位的位情况,然后是通过函数的递归实现进位与不进位的相加(这里不怎么好想,相当于进位结果和不进位结果又做为参数值进行“进位与不进位运算“),直到最后不产生进位,即a等于0,b值就是最开始参数的值的相加。
- 自定义过滤
- 请实现filter()函数:过滤满足条件的数组元素
- 提示:使用函数指针作为参数,并且你需要为它分配内存
typedef int (*Predicate)(int);
int *filter(int *array,int lenth, Predicate predicate, int *resultLenth);
int isPositive(int num){return num > 0;}
int main(void)
{
int array[] = {-3, -2, -1, 0, 1, 2, 3, 4, 5, 6};
int lenth = sizeof(array) / sizeof(array[0]);
int resultLenth;
int *filteredNumbers = filter(array, lenth, isPositive, &resultLenth);
for(int i = 0; i < resultLenth; i++)
{
printf("%d ",filteredNumbers[i]);
}
printf("\n");
free(filteredNumbers);
return 0;
}
代码如下:
int *filter(int *array,int lenth, Predicate predicate, int *resultLenth)
{
int *getarray=(int *)malloc(sizeof(int)*lenth);
int k = 0;
for(int i = 0;i < lenth;i++)
{
if(isPositive(array[i]))
{
getarray[k] = array[i];
k++;
}
}
*resultLenth = k;
return getarray;
}
- 静……态……
- 如何理解关键字static?
- static和变量结合后有什么作用
- static和函数结合后有什么作用
- static和指针结合后有什么作用
- static如何影响内存分配
我们从两方面去认识static的作用,一个是生命周期,一个是可见性。对于static修饰的内容,其生命周期都和程序相同,这样就延长了生命周期;然后是可见性上,static修饰后,我们就只能在本文件使用,即为内部链接,在其他文件上是无法调用的。(静态变量默认初始化为 0)。
- 救命! 指针!
- 数组指针是什么? 指针数组是什么? 函数指针ne? 用自己的话说出来更好o,下面数据类型的含义又是什么呢?
int (*p)[10];
const int *p[10];
int (*f1(int))(int *, int)
数组指针的本质是指针,它指向了某块“数组大小”的地址,如上的数组指针指向了一块10int大小的地址;
指针数组的本质数组,只是这个数组的元素是指针,如上的指针数组是有10个int的指针;
函数指针顾名思义,就是指向函数的指针,它包括了函数的返回值和参数,如上函数指针指向了一个返回值为int,参数为int和int的函数。
- 咋不循环了
- 程序直接运行,输出内容是什么意思
int main(int argc,char *argv[])
{
printf("[%d]\n",argc);
while(argc)
{
++argc;
}
int i = -1, j = argc, k = 1;
i++ && j++ || k++;
printf("i = %d, j = %d, k = %d\n",i, j, k);
return EXIT_SUCCESS;
}
main的参数请参考前文,对于循环,并不是循环没有进行,而是argc发生了上溢再从负值增为0。然后是逻辑表达式那行是完全执行的,从后面的输出也可以看出,需要注意的是&&优先级高于||。
最后提下EXIT_SUCCESS,它包含在stdlib.h头文件中的一个符号常量,表示一个程序的成功执行。
- 到底是不是TWO
#define CAL(a) a * a * a
#define MAGIC_CAL(a , b) CAL(a) + CAL(b)
int main(void)
{
int nums = 1;
if(16 / CAL(2) == 2)
{
printf("I'm TWO(丿>ω<)丿\n");
}
else
{
int nums = MAGIC_CAL(++nums, 2);
}
printf("%d\n", nums);
}
因为define是代换,所以if判断变成
16 / 2 * 2 * 2 == 2 //显然不成立
然后是关于
++nums * ++nums * ++nums
它的执行和具体环境有关,从而也造成在不同编译器下结果可能存在差异。
- 克隆困境
- 试运行一下程序,为什么会出现这样的结果?
- 直接将s2赋值给s1会出现哪些问题,应该如何解决?请写出相应代码
struct Student
{
char *name;
int age;
};
void initializeStudent(struct Student *student, const char *name, int age)
{
student->name = (char *)malloc(strlen(name) + 1);
strcpy(student->name, name);
student->age = age;
}
int main(void)
{
struct Student s1, s2;
initializeStudent(&s1, "Tom", 18);
initializeStudent(&s2, "Jerry", 28);
s1 = s2;
printf("s1 的姓名: %s 年龄:%d\n",s1.name, s1.age);
printf("s2 的姓名: %s 年龄:%d\n",s2.name, s2.age);
free(s1.name);
free(s2.name);
return 0;
}
程序出现的问题在最后的释放上,当我们将s2赋值给s1时,name指针都指向了同一块内存,然后我们第一次释放了这块内存,即第一个free,此时产生了一个问题,既然两个name指针都指向同一块内存,可我们已经释放了这块内存了,那么第二次释放的时候释放什么呢?问题就在这里,那么我们的解决方法就是给两个name指针都开辟一块空间,实现深拷贝。
s1 = s2;
s1.name =(char*)malloc(strlen(s1.name)+1);
strcpy(s1.name,s2.name);
- 你好,我是内存
- 作为一名合格的从C-Coder,一定对内存很敏感吧~来尝试理解这个程序吧!
struct structure
{
int foo;
union
{
int integer;
char string[11];
void *pointer;
}node;
short bar;
long long baz;
int array[7];
}
int main(void)
{
int arr[] = {0x590ff23c, 0x2fbc5a4d,0x636c6557, 0x20656d6f, 0x58206f74, 0x20545055,0x6577202c, 0x6d6f636c, 0x6f742065, 0x79695820, 0x4c20756f, 0x78756e69, 0x6f724720, 0x5b207075, 0x33323032, 0x7825005d, 0x636c6557, 0x64fd6d1d};
printf("%s\n", ((struct structure *)arr)->node.string);
}
不能说一模一样,只能说完全相同,画个内存情况:

加上地址
0x7fffffffe110 0x7fffffffe118 0x7fffffffe128 0x7fffffffe130 0x7fffffffe138
阿弥陀佛,善哉,善哉
1907

被折叠的 条评论
为什么被折叠?



