为了节省内存,C/C++内存模型把字符串常量放到单独的一个内存区域;
当几个指针指向相同的字符串常量的时候,他们实际上会指向常量区那个的内存地址;
但是用字符串常量初始化数组,情况却不一样.
求长度length、length()与size()
-
length属性是针对Java中的数组来说的,要求数组的长度可以用其length属性;
-
length()方法是针对字符串来说的,要求一个字符串的长度就要用到它的length()方法;
-
Java中的size()方法是针对泛型集合说的,如果想看这个泛型有多少个元素,就调用此方法来查看
地址、函数声明与定义
2018年11月5日的实验课上出现一些问题:
1. A与&A
若有数组int A[]={0,1,2};
1 | printf("%p\n",A) |
输出的结果是一致的,两者指向的同一块地址,不同的是A代表的是数组首元素的地址,&A代表的整个数组的地址。
所以当
1 | printf("%p\n",A+1) |
A+1增加的一个元素的内存大小(增加4);
&A+1增加的是整个数组的内存大小(增加12)
2. 函数的参数是数组,取地址
如果主函数中调用了f(A); f的定义如下
1 | int f(int x[]) { |
此时输出的并不同,后者x输出的是A的首元素地址,前者输出的x的地址(指针变量的地址)
3. 声明和定义的位置
助教课程中有同学程序出错,最后对错误的原因探索了一下。
一般说来,子函数的声明和定义,参数个数要一致,但是奇怪的是发现参数不一致有些情况下居然编译是正常的。
1 | #include <stdio.h> |
首先,c语言不支持重载。
在函数调用和定义参数不匹配时——
有声明(且声明和调用的参数上一致,否则编译先出错),编译出错
- 定义在main之前,编译出错。编译器先有了定义,读到调用的地方,会做参数个数类型检查(虽然并不完善),与先前定义的不一致,所以给出编译出错。
- 定义在main之后,编译出错。奇怪的是定义函数f时的参数若写成int x[],没有出错。应该是传递了什么地址直接给指针变量x了吧?待考察。
没有声明,编译大多数出错
- 定义在main之前,编译出错,同上解释;
- 定义在main之后,都是编译出错解释同上,但是除非:如果定义f的返回值是int(因为c语言默认函数的返回值都是int,对于main中的
f();
默认其是int,只有定义f的返回值也是int才相符)编译只是警告。因为在编译期间,没有声明,编译器不知道函数原型是什么,更别提什么检查。
那链接期检查吗,编译通过说明没有重载,链接期间以函数名作为符号的识别依据,发现函数名一致就通过链接阶段了。
综上所述,书写函数,把声明在开头写好(比如写进头文件),好好比对参数类型和个数。
换电脑后/系统后 同步github原有项目
*对于已有的仓库
在本地文件夹,打开终端
(一些命令省略了)
1 | git init 仓库名字 |
阅读报告_A [2017][IFIP]On Broadcast-based Self-Learning in Named Data Networ
论文题目
On Broadcast-based Self-Learning in Named Data Networking
论文作者、单位
Junxiao Shi, Eric Newberry, Beichuan Zhang ——The University of Arizona
发表的会议或者期刊
2017 IFIP C类会议
论文关键字
略
论文摘要原文
In local area networks and mobile ad-hoc networks,broadcast-based self-learning is a common mechanism to findpacket delivery paths. Self-learning broadcasts the first packet,observes where the returning packet comes from, then createsthe corresponding forwarding table entry so that future packetswill only need unicast. The main benefits of this mechanism areits simplicity, adaptability, and support of mobility. While thehigh-level idea of broadcast-based self-learning is straightforward,making the scheme efficient and secure, especially in adata-centric network architecture like Named Data Networking(NDN), requires careful examination. In this paper, we study howbroadcast-based self-learning may be applied to NDN networks,point out two major issues: the name-prefix granularity problemand the trust problem, and propose corresponding solutions. Wealso apply self-learning to switched Ethernet as an example todevelop a specific design that can build forwarding tables withoutany control protocol, recover quickly from link failures, and makeuse of off-path caches. Simulations are conducted using both realand synthetic traffic to evaluate the performance of the design.
论文摘要中文
在局域网、移动自组织网络中,基于广播的“自学习”是一种常见的找到包传递路线的方法。自学习方法广播第一个包,观察包从哪里回来,然后创建对应的转发表项,使得将来的包只需要单播即可。该方法的主要好处是简洁性、适用性、支持移动性。虽然基于广播的自学习的高层次思想很简单,但是为了使该方法更高效率、安全,尤其是在类似NDN的数据中心网络架构中,该方法仍需进一步检验。在本文中,我们研究了基于广播的自学习如何被应用于NND,指出了两个主要问题:名称前缀粒度问题、信任问题,并给出了对应的解决方案。
作为一个例子,我们还将自学习应用于交换式以太网,开发了一个具体设计——可以在没有任何控制协议的情况下构建转发表、快速从链路失效中恢复、利用其他线路的缓存。仿真同时使用了真实、合成的流量去评估设计的性能。
研究问题
介绍了自学习广播法。着重介绍了两个值得关注的地方——(1) FIB prefix的粒度问题; (2) 认证;
将该方法应用于以太交换局域网,介绍了如何构建转发表、从链路失效中快速恢复、利用缓存。
研究意义
Broadcast-based self-learning allows networks to adapt to changing environments and allows for producer mobility, without using any routing or other control protocols.
particularly notable in mobile ad hoc and wireless network environments.
This mechanism also fits the NDN architecture well because it does not require prior knowledge of the location of data.
研究内容(算法、方法、技术、模型)
- 前缀粒度问题
回来的Data,forwarder不知道producer的真实前缀。FIB里太具体和太短都不好。三个办法
- k最低按前缀:一律移去最后k个component。不必要的洪泛 优于 错转发IPkt,k设为较小。
- FIB 聚集:FIB项中多个公共前缀都指向相同的下一跳,聚合。
- prefix 公告:应答洪泛的IPKT时,把前缀公告作为链路层头附在Data上
研究结论、主要贡献
文章的思想很简单,在此基础上解决了粒度问题、验证问题,其实思路还是常见的。
个人觉得创新点不是很多,更多的工作体现在代码上吧。
技术难点
对本人工作的启发
对于链路失效时pending的兴趣包是让consumer重传;
而对于链路失效时刚到来的兴趣包是要么其他路,要么discovery兴趣包直接让forwarder重传,要么逐跳返回NACK
ndnSIM场景文件的放置
nsnSIM自己的场景文件放的方式有两种:
- 第一种可以放在自己的目录里编译速度很快,而且要NS-LOG只能在debug模式下使用,这时场景文件必须放在自己的目录下(我理解是这样,若错了请及时反馈我);但是修改程序源文件后要去不同目录下先编译;
- 第二种方式是把场景文件直接放在examples目录下,配置时直接在ns-3下
./waf configure --enable-examples
和./waf
,编译速度较慢,但是之后无论是修改NFD、cxx还是场景文件,直接在ns-3 下 ./waf --run(发现可以同时完成编译和运行)
1. 创建自己的目录里放自己的场景文件
Step 1
1 | mkdir ndnSIM |
Step 2:编译
1 | 每次修改完情景文件,都要在my-simulations目录下 ./waf |
Step 3:运行
1 | 在在my-simulations目录下 ./waf --run <scenario_name> --vis |
2. 另一种方式(编译速度较慢)
不使用自己的目录的话,可以把场景文件放在exampls下,以后每次在ns-3 下,直接./waf --run <scenario_name> --vis
少年班的助教课引发的二分查找法变形
题目
最近少年班的C语言课上老师出了一道题目,题目要求先排序,再给一个元素进行二分查找,最后把该元素key插入到数组中仍然有序。
在上机课前思考了一下,假如说元素是往后挪的,如何找出最合适的位置,使得需要挪动的元素个数最小。
- 对于key元素没有重复的一组数,二分查找出的位置(right指针)就是待插的位置。
- 但是key这个数有重复的一组数,二分查找出的位置不一定能保证挪动次数最少。应该要找到第一个大于key的数的位置,在这个位置插入key,才能保证挪动次数最少。
分析
这个问题,其实是变形二分法的一种。最开始想法是仍就用基本的二分法,最后在加一for循环,一个个元素比对过去找出最合适的值。可是,这样子又把查找插入位置的时间复杂度提高到了O(n),能否通过修改二分查找法,直接找出那个位置的。
答案是可以的。开始之前,先看下基本的二分查找法:
1 | //基本的二分法 |
这个代码很简单,要注意while循环里的=不要忘。
首先来看下查完之后,left、right的位置:
- 查到的话要么l与r在mid等距的两边; 要么left=mid,r=l或r=left+1;
- 查不到的话right<left,刚好夹在key两侧
变形的二分查找种类很多,诸如找出第一个与key相等的元素、找出最后一个与key相等的元素……
改的话要:- 删去
if (arr[mid] == key) return mid;
因为mid不一定是合适的位置 - 修改
if (arr[mid] > key)
的大于符号 因为要对right、 left的位置和基本版不同 - 循环结束后要返回查到的位置或返回无结果;
- 删去
如何改这些,主要是要先分析两步:根据问题要求确定left和right的最终位置(要返回left还是right)、结合题目要求修改比较符号。
以“查找第一个与key相等的元素位置”为例,假如一组数1,2,3,3,4,5,待查的数是3。
第一步: 因为删去了if (arr[mid] == key) return mid;
,所以while循环结束时,肯定是left > right
,而且这两个数肯定要是在边界上,如下图所示。这样我们返回left就是answer了。
第二步: 那怎么修改比较符号呢,原来if (arr[mid] > key) right = mid - 1;
每一轮循环里,只有a[mid]是比key大,right才会变化。现在呢,不仅a[mid]比key大时right要改,当a[mid]等于key时,right也得改,这样它才能挪到元素2那里。因此改为if (arr[mid] >= key) right = mid - 1;
最后针对iii: 因为返回的是left,所以对left做一些限定if (left < n && arr[left] == key) return left;
代码实现
代码把基本的二分查找,以及六种变形情况实现了一下,最重要的地方都有注释
1 | public class ExtendeBinarySearch { |
测试结果
1 | int arr[] = new int[] {1, |
兴趣包或数据包增加自定义字段
NDN Maillist提了不少关于增加和修改自定义字段的问题,一直没有明确的答复。2018年9月份有人又提了,趁最近做实验,把这一问题做个总结。
- 往包里添加字段,但是中途不能改的 https://blog.csdn.net/aladeen/article/details/78798093
- 往包里添加字段,可以改的(今日工作)
https://lo.calho.st/networks/adding-custom-packet-fields-to-packets-in-ndnsim-2-3-without-forking-the-entire-repository/
getTag setTag 可以放在onOutgoingData() ,consumer.cpp 或producer.cpp 里也可以设置这样包里的东西可以传递了
网页里Investigation之后的总结如下:
智能指针
最近在看NFD的源码是经常看到类似shared_ptr<Data> dataCopyWithoutTag = make_shared<Data>(data);
翻阅C++ Primer对这个做了大致解释如下:
在C中,动态内存的管理是通过一对运算符来完成的:new,在动态内存中为对象分配空间并返回一个指向该对象的指针,可以选择对对象进行初始化;delete,接受一个动态对象的指针,销毁该对象,并释放与之关联的内存。
动态内存的使用很容易出问题,因为确保在正确的时间释放内存是极其困难的。有时会忘记释放内存,在这种情况下会产生内存泄露;有时在尚有指针引用内存的情况下就释放了它,在这种情况下就会产生引用非法内存的指针。为了更容易(同时也更安全)地使用动态内存,C11标准库提供了两种智能指针(smart pointer)类型来管理动态对象。 智能指针的行为类似常规指针,重要的区别是它负责自动释放所指的对象。C11标准库提供的这两种智能指针的区别在于管理底层指针的方式:shared_ptr允许多个指针指向同一个对象;unique_ptr则"独占"所指向的对象。C11标准库还定义了一个名为weak_ptr的辅助类,它是一种弱引用,指向shared_ptr所管理的对象。这三种类型都定义在memory头文件中。**智能指针是模板类而不是指针。**类似vector,智能指针也是模板,当创建一个智能指针时,必须提供额外的信息即指针可以指向的类型。默认初始化的智能指针中保存着一个空指针。智能指针的使用方式与普通指针类似。解引用一个智能指针返回它指向的对象。如果在一个条件判断中使用智能指针,效果就是检测它是否为空。
阿里巴巴Java开发手册查漏补缺
阿里巴巴Java开发手册查漏补缺
一、编程规范
(一)命名风格
- 5 常量名全部大写,单词之间下划线:MAX_STOCK_COUNT
- 7 数组定义:String[] args
- 8 POJO类中布尔类型的变量,都不要加 is,否则部分框架解析会引起序列化错误。
(二)常量定义
- 2 long型赋值,用大写的L,Long a=2L;
(三)代码格式
- 1 大括号
1 | if (a == b) { |
- 4 任何二目、三目运算符的左右两边都需要加一个空格:
a == b
、a = b
- 5 采用4个空格缩进
- 6 注释的双斜线与注释内容之间 有且仅有一个空格
- 7 单行字符超过120个字符换行,第二行相对第一行继续缩进4字符,第三回不继续缩进
- 8 方法参数在定义和传入时,多个参数逗号后边必须加空格
method("a", "b", "c");
- 9 IDE的text file encoding设置为UTF-8;
(四) OOP 规约
- 1 静态变量或静态方法,直接使用类名访问
- 2 所有的覆写方法,必须加@Override 注解。
- 6 Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。
- 15 类内方法定义顺序依次是:公有方法或保护方法 > 私有方法 > getter/setter 方法。
- 19 Object实现的是浅拷贝
(五)集合处理
(六)并发处理
(七)控制语句
- 1 在一个 switch 块内,都必须包含一个 default 语句并且 放在最后,即使它什么代码也没有。
- 2 if wlse for while do语句必须有大括号,
(八)注释
- 1 Javadoc注释
- 5 枚举字段要有注释
- 11 代办事宜(TODO):(标记人,标记时间,[预计处理时间])
错误,不能工作(FIXME):(标记人,标记时间,[预计处理时间])
(九)其他
- 4 注意 Math.random() 这个方法返回是 double 类型,注意取值的范围 0≤x<1(能够 取到零值,注意除零异常),如果想获取整数类型的随机数,不要将 x 放大 10 的若干倍然后 取整,直接使用 Random 对象的 nextInt 或者 nextLong 方法。
- 5 获取当前毫秒数 System.currentTimeMillis();如果想获取更加精确的纳秒级时间值,使用 System.nanoTime()的方式