0鼠鼠我啊,要被祸害了
将所有药瓶编码后转为二进制,(1000)10=(1111101000)2,故需要十只老鼠,接着一次处理各个二进制编码,对为1的位老鼠喂药,对为0的老鼠不作处理,24小时后,死亡位为1,存活位为0,将数字转化为十进制就是有毒的药水。
1.先预测一下~
在welcome
函数中返回指向字符串的指针,并在主函数中打印出字符串。
char *welcome() {
// 请你返回自己的姓名
}
int main(void) {
char *a = welcome();
printf("Hi, 我相信 %s 可以面试成功!\n", a);
return 0;
}
首先定义一个welcome函数返回字符串的指针,然后在主函数中定义一个指针a赋值为welcome的返回值,并用%s打印出来。
2欢迎来到 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);
}
首先声明指向"Welcome to Xiyou Linux!"
的指针ptr0,在声明内容为"Welcome to Xiyou Linux!"的数组ptr1,利用if语句比较两个数组首字符后发现相等,于是打印,先从最内层开始运行,发现返回值为0,将次外层的%d转换为0,由于此处有23个字符,所以给最外层返回23,于是最终输出为
Hello, Linux Group - 2023`。
3一切都翻倍了吗
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
- strlen()包含于<string,h>中,一般用于返回字符串长度,是一个函数;而sizeof()是一个运算符,括号中可以加入变量类型或者变量,返回该变量类型所占字节大小。若加入数组名,则返回数组所占字节数,即数组长度*数组元素所占空间的大小。
- sprintf()将数据写入字符串中,第一个参数为待写入的目标字符串地址,后面的参数与printf相同,返回值为写入字符的总数(不包含控空字符)。若读取失败则返回负值。
- 解释程序的输出:*&arr相当于在sizeof中加入数组名,arr + 0返回值为arr的元素所占字节数,num = num2 + 4的返回值为short类型所占字节数。在
printf("%d\n", sprintf(str, "0x%x", num) == num);
中sprintf返回4,不等于num,,故給最前面的%d返回0。最后一行strlen()从str数组的第二项开始读,此时str数组中共有五个字符,故返回4。第二个从第一项开始读,故返回5。
4.奇怪的输出
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);
}
输出如下
a = 64 b = 63 c = -1
ch = -128
(64)10=(1000000)2,(127)10=(1111111)2
64与127按位与运算的结果为64,,按位异或运算的结果为63,-64向右移位6位后结果为-1,最终ch的运算结果为-128.
5乍一看就不想看的函数
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)));
}
- 要实现两个数的加法,可以利用异或和按位与运算实现。将两数的异或结果与直接加对比发现,只差二进制进位信息。而两数的按位与运算结果与进位信息只差左移一位,故将其左移一位。
- 当进位信息为0时,异或结果即加法结果。故使用func函数递归,当a为0时,返回结果。
- 图中为4+9+(-7)的结果。
6自定义过滤
typedef int (*Predicate)(int);
int *filter(int *array, int length, Predicate predicate,int *resultLength); /*补全函数*/
int isPositive(int num) { return num > 0; }
int main(void) {
int array[] = {-3, -2, -1, 0, 1, 2, 3, 4, 5, 6};//array数组
int length = sizeof(array) / sizeof(array[0]);//length=10
int resultLength;
int *filteredNumbers = filter(array, length, isPositive,&resultLength);
for (int i = 0; i < resultLength; i++)
{
printf("%d ", filteredNumbers[i]);
}
printf("\n");
free(filteredNumbers);
return 0;
}
补全后的函数如下:
#include <stdio.h>
#include <stdlib.h>
typedef int (*Predicate)(int);
int *filter(int *array, int length, Predicate predicate,int *resultLength); /*补全函数*/
int isPositive(int num) { return num > 0; }
int main(void) {
int array[] = {-3, -2, -1, 0, 1, 2, 3, 4, 5, 6};//array数组
int length = sizeof(array) / sizeof(array[0]);//length=10
int resultLength;
int *filteredNumbers = filter(array, length, isPositive,&resultLength);
for (int i = 0; i < resultLength; i++)
{
printf("%d ", filteredNumbers[i]);
}
free(filteredNumbers);
return 0;
}
int *filter(int *array,int length,Predicate predicate,int *resultlength)
{
int *arr=(int *)malloc(sizeof(int)*length);
int numb=0;
for(int i=0;i<length;i++)
{
if(predicate(array[i]))
{
arr[numb]=array[i];
numb++;
}
}
*resultlength=numb;
return arr;
}
该函数为定义一个能过滤数组大于0的元素的元素,为此使用filter()在传入四项对应的参数后,在创建一个新数组arr来存储大于0的元素,并将元素个数传递回主调函数。
7静…态…
- static修饰静态变量
- static修饰局部变量时会改变该变量的生命周期(与程序一致),变得不会销毁变量,一直有效。
- static修饰全局变量时会改变其链接属性,从外部链接改为内部链接,作用域变小。
- static修饰函数时同理,变为内部链接,其他源文件不能使用该函数。
- static修饰指针时也会使其作用域变小,生命周期不变。
- static修饰的东西,在编译时就会为其分配内存空间,直到程序结束时才销毁。
8救命!指针!
-
数组指针是指向数组的指针。eg: int (* pi) [4]
-
指针数组是内部元素均为指针的数组。eg:int * pi [4]
-
函数指针是指向函数的指针。eg: int (*func) (int)
-
int (*p)[10];
声明了一个指向含十个int类型元素的指针p。
-
const int* p[10];
声明了一个不可更改指向的值的内含十个指针元素的数组p。
-
int (*f1(int))(int*, int);
将f1函数的返回值设为指向参数为 int*,int且返回值为int的函数指针。
9咋不循环了
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; }
- 该函数中,argc是传递给命令行参数的数量,至少为1,是它本身。argv是一个指向字符串的指针,每个字符串是一个命令行参数,地一个元素是程序的名称。
- int类型为32位,argc由0开始递增,到最大时变为最小的负数,并递增到0退出循环。
- 此时j=0,0与-1与结果为0,0与1或结果为1,并打印出递增后的结果,为0,1,2。
10.到底是不是 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); }
宏定义相当于直接带入,在if语句中没有给立方运算带括号,无效进入else语句,然而在if语句内创建的变量在if语句外是失效的,所以nums还是最开始定义的1,最后打印出来1。
11克隆困境
试着运行一下程序,为什么会出现这样的结果? 直接将 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; }
运行结果为
s1 的姓名: Jerry 年龄: 28 s2 的姓名: Jerry 年龄: 28
- 首先封装一个结构体类型Student,其中包含了一个char字符串和一个int类型值。
- 在initializeStudent函数中传入Student的指针,字符串指针和int值,手动为naem分配空间后将name指针指向它,然后将name和age加入结构体中。
- 主函数在声明两个Stduent类型后分别封装入元素,然后将s1的值修改为s2,此时&s1与&s2共同指向s2,打印。
- 随后释放空间时由于两指针相同,多free了一次,原来的s2还没释放。释放完还要给指针赋值null。
12你好,我是内存
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); }
结果如下
Welcome to XUPT , welcome to Xiyou Linux Group [2023]
structure结构体的最大的对齐数为8,最后一行中首先将arr数组强制转换成指向structure的指针,然后解引用到node联合体中的string数组中,foo首先占前面四个字节(小端序存储字符),然后union对齐到第八个字节处,由57开始打印,最终输出为图上,一直到空字符\0结束。
13.GNU/Linux (选做)
注:嘿!你或许对 Linux 命令不是很熟悉,甚至你没听说过 Linux。但别担心,这是选做题,了解
Linux 是加分项,但不了解也不扣分哦!
你知道 cd 命令的用法与 / . ~ 这些符号的含义吗?
请问你还懂得哪些与 GNU/Linux 相关的知识呢~
cd加目录名为进入或切换到该文件夹中。
当表示相对路径时,路径名前面不是/或者~,而表示绝对路径时,即从根目录或者家目录开始的路径,在路径名前面加/或~。