作者 | 阿文
责编 | 伍杏玲
出品 | 程序人生(ID:coder_life)
近日,一段“小伙骑车逆行被拦后爆发”的视频在网络热传,很多网友看了之后都评论说,仿佛看到了自己。
一辆骑车逆行的小伙子,当被交警拦下后,小伙先是平静地给女友打电话说"我逆向行车被抓了,现在走不了,你在那儿等我吧。"挂完电话,小伙就出人意料地将手机摔了。
随后小伙情绪激动,并跪倒在地,失声痛哭起来。还突然跑向路边一座桥,趴在了桥栏上。民警担心他有轻生的念头,一把把他拉过来。
经过了解小伙子觉得自己压力好大,每天加班到十一二点,因为女朋友回家没带钥匙,他骑车是要给女去送钥匙,单位和女朋友都在催着他,他真的好烦,只想哭一下。
当代中国青年压力太大了,工作时长是罪魁祸首,根据调查,中国人年均工作2000至2200小时,而英国人年均工作为1677小时,日本人年均工作1729小时,可见中国年轻人的工作时间要远远超过大多数国家的年轻人。
今年以来 996 这个话题已经被讨论了好多次:从年初杭州有赞在年会公开宣布 996 被网友吐槽甚至举报到劳动局。其实,有赞的 996 只不过是把平时大多数企业一直在做的事情摆到了台面上而已。
而GitHub 上最火的996.ICU 项目被 Star 十五万,该项目是 IT 从业者发起的一项倡议,要求雇主尊重雇员的合法权益。
现实版摩登时代
卓别林的《摩登时代》讲述的是在20世纪的美国,时值美国经济大萧条的高峰期,在此期间,社会经济虽然有一定发展,但是资本主义制度的基本矛盾依然存在。
资本家攫取了高额利润,广大劳动人民却日益贫困,资本家为眼前的利润驱使,盲目地扩大生产,使得生产和销售之间的矛盾日益尖锐。
穷人想尽一切办法艰难度日,常常食不果腹,衣不御寒。而资本家为了维持商品价格,保证利润,不惜大量销毁商品。
工人查理(卓别林饰)在工厂干活、发疯、进入精神病院的经历,正是讽刺了本应以提高劳动生产率、减轻体力劳动为目的的机械化,实际上却加重了工厂对工人的压榨。连工人吃饭的时间都一省再省,而工人查理便是这群弱势群体的代表人物。社会中的每一个人都在自己的生活中苦苦挣扎。
马克思在《资本论》中曾经引用托·约·登宁《工会与罢工》的话:“一有适当的利润,资本就胆大起来。如果有10%的利润,它就保证到处被使用;有20%的利润,它就活跃起来;有50%的利润,它就铤而走险;有100%的利润,它就敢践踏一切人间法律;有300%的利润,它就敢犯任何罪行,甚至冒绞首的危险。”
相比较卓别林那个时代,现如今的工业和科技发展水平已经远远超过当时的水平了,然而事实是底层人民的工作时间却丝毫没有变化,还是被以各种直接或间接的方式进行压榨。
我想起了张养浩的《山坡羊·潼关怀古》中的诗句"兴,百姓苦;亡,百姓苦"。
我们这届年轻人正是在被高企的房价透支着未来,被996透支着健康。
作为金字塔底层的劳苦大众,我们都深知我们并没有多少资本和能力去反抗这种不公平的规则和制度。唯一一部能够保护劳动者的《劳动法》似乎并不能给底层劳动者带来什么特别大的帮助。
自1995年1月1日起施行的《劳动法》颁发及修改至今已经快 19 年,有多少企业是严格按照劳动法的法律法规来保障职工的基本权益的?我看到的是很多中小企业连职工最基本的养老保险都不缴纳甚至最低额度缴纳,却一天天打鸡血一样要求员要有奋斗精神,要有狼性,狼是要吃肉的,你给员工吃的是肉吗?
不要大声责骂年轻人,他们会立刻辞职的,但是你可以往死里骂那些中年人,尤其是有房有车有娃的那些。 然而年轻人也有成为中年人、会有房有娃的那一天。
马斯洛的需求层次理论最底层是生理需求,然而被加班所裹挟的年轻人,这个基本的需求都无法得到满足。何谈更上层的各种需求?
你远没有想象的那么重要
可能大多数人会有一种幻觉,那就是觉得自己的技术好的有话语权。事实上,这确实是会占一部分比例,但是大多数人都达不到这个要求,像乔布斯都曾经被赶出自己的公司,何况广大底层的码农们。
互联网诞生至今已经30几年了,各种产品基本都是基于开源的项目二次开发或者借鉴这些项目和成熟的工具来做开发,都是一些成熟的框架和工具,并且每年都会有一大批廉价的毕业生以及各种培训机构培养一批一批的人员供市场选择,就像流水线一样批量化生产。
一个成熟的企业,都有自己的一套非常标准的流程和体系,不会因为缺一个人就导致整个项目无法运作,大多数岗位只需要负责一些被拆分后非常细化的领域做一些基本开发工作,而且每一步都会有标准化的流程,你很难接触到整个项目的开发流程,换句话说你只不过是一个拧螺丝的而已。
况且随着年龄的增大以及家庭负担等因素,身体各项机能和学习能力会自然而然的退化,相比较年轻人,你的优势会越来越比不过年轻人。
现在社会没有人能够保证你可以在一家企业干到退休,华为等知名互联网公司都在以各种方式驱赶那些中年人和老人,原因就是年轻人比你更便宜,更有活力。
那么,作为普通人,我们如何才能逃脱这种被安排的“宿命”呢?
首先,我希望类似 996.ICU 这类项目可以得到更多人的认可和关注,希望大环境越来越好。
还有我们改变自己吧,作为一个普通码农,不仅仅要埋头苦干,还要抬头向前,千万不要盯着工作上那一亩三分地就止步不前,一定要学会投资。
这里的投资,不仅仅要学会理财,更重要的是要学会投资自己,投资自己的大脑,多学习,提升自己的核心竞争力,早日摆脱底层码农的命运。
其次,要学会分散投资,千万不要把所有的期望都寄托在一家单位身上。一定要在主业稳定后寻求副业。把鸡蛋放在不同的篮子里面,分散风险。
最后,一定要记得定期体检和锻炼,身体是革命的本钱,这才是最关键的。
成年人的世界里,没有容易二字。不仅仅是互联网从业者,各行各业的从业者都在被时代这座机器拉着快速向前,作为个体我们没有办法放慢脚步停止不前,一旦停止,那便就真的可能被淘汰了。
被这多大企,程序员追捧的Python到底2019年前景如何?
热 文 推 荐
☞ 程序员找工作黑名单:除了 996.ICU,程序员还将如何自救?
☞ 30 位 90 后霸榜:名企 CEO、10 亿身家,马云的接班人?
☞ 何恺明的GN之后,权重标准化新方法能超越GN、BN吗? | 技术头条
☞ 2019年关于VM和Kubernetes的思考 | 技术头条
System.out.println("点个在看吧!");
console.log("点个在看吧!");
print("点个在看吧!");
printf("点个在看吧!\n");
cout << "点个在看吧!" << endl;
Console.WriteLine("点个在看吧!");
Response.Write("点个在看吧!");
alert("点个在看吧!")
echo "点个在看吧!"
点击阅读原文,输入关键词,即可搜索您想要的 CSDN 文章。
你点的每个“在看”,我都认真当成了喜欢



目录
四.用冒泡排序思想,模拟实现 qsort (可排序任意类型数据)
一.冒泡排序
对数组进行排序,升序。思想:两两相邻元素比较
- void bubble_sort(int arr[], int sz)
- {
- //趟数
- int i = 0;
- for (i = 0; i < sz - 1; i++)
- {
- //一趟冒泡排序的过程
- int j = 0;
- for (j = 0; j < sz - 1 - i; j++)
- {
- if (arr[j] > arr[j + 1])
- {
- int tmp = arr[j];
- arr[j] = arr[j + 1];
- arr[j + 1] = tmp;
- }
- }
- }
- }
-
- int main()
- {
- int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
- int sz = sizeof(arr) / sizeof(arr[0]);
- bubble_sort(arr, sz);
-
- //打印 0 1 2 3 4 5 6 7 8 9
- int i = 0;
- for (i = 0; i < sz; i++)
- {
- printf("%d ", arr[i]);
- }
-
- return 0;
- }
10个元素9趟,sz 个元素 sz-1 趟。
第一趟10个元素比较9次,第二趟9个元素比较8次 ......
缺点:只能排序整数。因为他的参数已经写死了,只能是整形数组。想排序字符数组、浮点型、结构体......做不到。他的功能非常有限。
二.指针类型 void*
先跳过,看完 三.2.后,回来看。
为什么 qsort 的参数写的 void*(无具体类型的指针) ?
因为:函数设计者,不知道未来你会比较什么类型的数据。
- int a = 10;
- float f = 5.5f;
- int* p = &a;//编译器没报错
- p = &f;//编译器报错:从“float *”到“int *” 的类型不兼容
-
- void* pp = &f;//不报错
- pp = &a;//不报错
可以把 pp 理解为通用的指针。(垃圾桶)谁的地址往进放。
缺点:放进去,不能直接用
- float f = 5.5f;
- void* pp = &f;
- printf("%f", *pp);
void* 类型的指针不能直接解引用。它没有具体类型,自己都不知道自己是啥类型
pp++; 也不行。无具体类型,它也不知道它 + 一步,+ 多远
当你都不知道未来别人给你传谁的地址时,用 void* 类型的指针接收
怎么用?指针类型可以转换
接着看 三.3.
三. qsort
qsort 内部的细节大家先不要关心,回头小编带大家模拟实现
1.简介
是库函数里提供的一个排序函数,底层用的是快速排序。头文件 #include
2.研究函数参数
一共4个参数:1.待排序数组的起始地址。2.元素个数。3.一个元素的大小(字节)。
4.(函数指针)。int (*compar)(const void* e1, const void* e2)
先分析,对上面的 bubble_sort 函数部分进行改造。希望函数可以排整型、浮点型、结构体......(任意类型数据),但还是用冒泡排序的思想,趟数和一趟比较的对数都不用变。
11-15行要变,因为:两个整型可以直接用 > 比较。但两个结构体元素不能用 > 比。
不同数据的比较方法不一样,交换方式不一样
想让他排任意类型的数据,把比较两个元素的方法抽离出来。
比如:程序员A 想排序两个整型,自己提供两个整型的比较方法;想排序结构体,自己提供两个结构体的比较方法。
再把比较的方法传进来,你按照我的方法比较这两个元素就可以。
其实,qsort 就是这么实现的。自己写个比较两个东西函数,把函数的地址传给 qsort ,恰好用(*compar)这个函数指针接收。然后 qsort 里面就按照这个函数指针指向的函数来比较。注意:&函数名 函数名 都是地址
写的函数就被称为回调函数
e1 e2 分别是要比较的两个元素的地址
3.怎么用?
(1)排数组,升序
- #include
- cmp_int()
- { }
-
- int main()
- {
- int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
- int sz = sizeof(arr) / sizeof(arr[0]);
-
- qsort(arr, sz, sizeof(arr[0]), cmp_int);// 这里是函数cmp_int 的地址
-
- int i = 0;
- for (i = 0; i < sz; i++)
- {
- printf("%d ", arr[i]);
- }
-
- return 0;
- }
要把 cmp_int 的地址传给 qsort 所需要的(*compar) 函数指针。
cmp_int 的参数、返回类型要与 qsort 的第四个参数的函数指针的参数、返回类型 保持一致
- #include
-
- //实现一个比较整形的函数
- int cmp_int(const void* e1, const void* e2)
- {
- //(int*)e1 把e1当成整型指针了
- return *(int*)e1 - *(int*)e2;
- }
-
- int main()
- {
- int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
- int sz = sizeof(arr) / sizeof(arr[0]);
-
- qsort(arr, sz, sizeof(arr[0]), cmp_int);// 这里是函数cmp_int 的地址
-
- int i = 0;
- for (i = 0; i < sz; i++)
- {
- printf("%d ", arr[i]);
- }
-
- return 0;
- }
cmp_int 实现了比较 e1 e2 指向的两个整型。把 cmp_int 的地址传给 qsort
qsort 就知道了,说:你让我 比较 arr 里 sz 个元素,每个元素大小为 sizeof(arr[0]),数组arr里两个元素的比较方法是 cmp_int
想降序:return *(int*)e2 - *(int*)e1;
(2)排序结构体
1.按照学生年龄排序
- #include
-
- struct Stu
- {
- char name[20];
- int age;
- };
-
- int cmp_stu_by_age(const void* e1, const void* e2)
- {
- // (struct Stu*)e2 - e2强制转化为结构体类型指针
- return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
- }
-
- int main()
- {
- struct Stu s[3] = { {"zhangsan",20}, {"lisi", 50}, {"wangwu", 33} };
- int sz = sizeof(s) / sizeof(s[0]);
- qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
-
- return 0;
- }
2.按照学生名字排序
- #include
- #include
- struct Stu
- {
- char name[20];
- int age;
- };
-
- int cmp_stu_by_name(const void* e1, const void* e2)
- {
- return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
- }
-
- int main()
- {
- struct Stu s[3] = { {"zhangsan",20}, {"lisi", 50}, {"wangwu", 33} };
- int sz = sizeof(s) / sizeof(s[0]);
- qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
-
- return 0;
- }
四.用冒泡排序思想,模拟实现 qsort (可排序任意类型数据)
1.函数参数设计
参数1:为了能够接受任意类型地址,用 void* 。 参数2:元素个数
为什么 qsort 要传元素大小?
void* 无具体类型,只知道待排序数组元素个数,不知道一个元素占几个字节
参数3:宽度 参数4:提出比较方法
类型最好给 size_t ,个数、宽度永远是正数
- //实现一个比较整型的函数
- int cmp_int(const void* e1, const void* e2)
- {
- return *(int*)e1 - *(int*)e2;
- }
-
- void bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* e1, const void* e2))
- {
- //趟数
- int i = 0;
- for (i = 0; i < sz - 1; i++)
- {
- //一趟冒泡排序的过程
- int j = 0;
- for (j = 0; j < sz - 1 - i; j++)
- {
- if (cmp() > 0)
- {
- //交换
- }
- //if (arr[j] > arr[j + 1])
- //{
- // int tmp = arr[j];
- // arr[j] = arr[j + 1];
- // arr[j + 1] = tmp;
- //}
- }
- }
- }
-
- void test3()
- {
- int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
- int sz = sizeof(arr) / sizeof(arr[0]);
- bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
- int i = 0;
- for (i = 0; i < sz; i++)
- {
- printf("%d ", arr[i]);
- }
- }
-
- int main()
- {
- test3();
-
- return 0;
- }
2.在 if (cmp( )>0) 怎么传参?
相邻两元素比较,传过来要是两元素的地址。比如,传9 8地址。怎么算呢?
现在不知道里面放的什么类型的元素,没法直接用下标来搞。只能通过偏移量来算。
8的地址是 base + 几。但 base 是 void* ,不能直接加。
强制类型转换。转换成什么类型?
int ? 不行,写死了。
怎么办?9的宽度是 width,从9偏移 width 个字节来到8。怎么来到8呢?
宽度 width 的单位是字节,如果把它转换成 char* 的指针,char* 的指针+width=跳过width个字节
- if(cmp((char*)base, (char*)base + width) > 0) //只是第一对元素
-
- if(cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
- {
- //交换
- }
if 里面是分别对应下标为 j j+1 元素的地址,分别传给 e1 e2 指针
cmp是比较函数,e1 e2 是它比较的两个元素
我们已经把待比较的两个元素的地址传给 e1 e2 。cmp 就通过这样一个指针找到它所指向的比较函数。如果比较函数返回值 >0 就交换
3.怎么交换?
给一个Swap 函数,把(char*)base + j * width , (char*)base + (j + 1) * width) 两个指针指向的元素交换。
交换这两个元素的宽度是多大呢?注意:我不知道我交换的两个元素多大。把 width 传过去
比较的时候都不知道比较谁,交换时也肯定不知道交换的是什么类型的数据,所以通过类型是没办法
- if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
- {
- //交换
- Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
- }
但是注意,当我要交换两个结构体的时候。我们没办法创建出10字节的临时空间,但是可以创建一个字节的空间。
交换每一对字节,这两个元素整体也就交换了
- //已经强制转换为char*,这里也不端着了,就写成char* 的指针
- void Swap(char* buf1, char* buf2, int width)
- {
- int i = 0;
- for (i = 0; i < width; i++)
- {
- char tmp = *buf1;
- *buf1 = *buf2;
- *buf2 = tmp;
- buf1++;
- buf2++;
- }
- }
五.整体代码
- #include
- #include
-
- struct Stu
- {
- char name[20];
- int age;
- };
-
- int cmp_stu_by_age(const void* e1, const void* e2)
- {
- return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
- }
-
- int cmp_stu_by_name(const void* e1, const void* e2)
- {
- return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
- }
-
- //实现一个比较整型的函数
- int cmp_int(const void* e1, const void* e2)
- {
- return *(int*)e1 - *(int*)e2;
- }
-
- //已经强制转换为char*,这里也不端着了,就写成char* 的指针
- void Swap(char* buf1, char* buf2, int width)
- {
- int i = 0;
- for (i = 0; i < width; i++)
- {
- char tmp = *buf1;
- *buf1 = *buf2;
- *buf2 = tmp;
- buf1++;
- buf2++;
- }
- }
-
- void bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* e1, const void* e2))
- {
- //趟数
- size_t i = 0;
- for (i = 0; i < sz - 1; i++)
- {
- //一趟冒泡排序的过程
- size_t j = 0;
- for (j = 0; j < sz - 1 - i; j++)
- {
- if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
- {
- //交换
- Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
- }
-
- }
- }
- }
-
- //使用我们自己写的bubble_sort函数排序整型数组
- void test3()
- {
- int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
- int sz = sizeof(arr) / sizeof(arr[0]);
- bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
- int i = 0;
- for (i = 0; i < sz; i++)
- {
- printf("%d ", arr[i]);
- }
- }
-
- //使用我们自己写的bubble_sort函数排序结构体数组
- void test4()
- {
- struct Stu s[3] = { {"zhangsan",20}, {"lisi", 50}, {"wangwu", 33} };
- int sz = sizeof(s) / sizeof(s[0]);
- bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_age);
- bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_name);
- }
-
- int main()
- {
- test3();
- test4();
-
- return 0;
- }
评论记录:
回复评论: