指针的理解

深入理解指针:一文让你彻底理解指针 好多人都说指针很难,其实指针并不难,你不是不懂指针,你是不懂内存管理,搞懂内存管理,指针就是纸老虎 阅读详情

http://blog.sina.com.cn/s/blog_491fee8d010009sa.html

 针 (Pointers)详解

 
指针 (Pointers)

我们已经明白变量其实是可以由标识来存取的内存单元。但这些变量实际上是存储在内存中具体的位置上的。对我们的程序来说,计算机内存只是一串连续的单字节单元(1byte cell),即最小数据单位,每一个单元有一个唯一地址。

计算机内存就好像城市中的街道。在一条街上,所有的房子被顺序编号,每所房子有唯一编号。因此如果我们说芝麻街27号,我们很容易找到它,因为只有一所房子会是这个编号,而且我们知道它会在26号和28号之间。

同房屋按街道地址编号一样,操作系统(operating system)也按照唯一顺序编号来组织内存。因此,当我们说内存中的位置1776,我们知道内存中只有一个位置是这个地址,而且它在地址1775和1777之间。


地质操作符Address (dereference) operator (&)

当我们声明一个变量的同时,它必须被存储到内存中一个具体的单元中。通常我们并不会指定变量被存储到哪个具体的单元中—幸亏这通常是由编译器和操作系统自动完成的,但一旦操作系统指定了一个地址,有些时候我们可能会想知道变量被存储在哪里了。

这可以通过在变量标识前面加地址符ampersand sign (&)来实现,它表示"address of"。例如:

ted = &andy;

将变量andy的地址赋给变量ted,因为当在变量名称andy 前面加ampersand (&) 符号,我们指的将不再是该变量的内容,而是它在内存中的地址。

假设andy 被放在了内存中地址1776的单元中,然后我们有下列代码:

andy = 25;
fred = andy;
ted = &andy;

其结果显示在下面的图片中:

指针的理解(转)

我们将变量andy 的值赋给变量fred,这与以前我们看到很多例子都相同,但对于ted,我们把操作系统存储andy的内存地址赋给它,我们想像该地址为1776 (它可以是任何地址,这里只是一个假设的地址),原因是当给ted 赋值的时候,我们在andy 前面加了ampersand (&) 符号。

存储其它变量地址的变量(如上面例子中的ted ),我们称之为指针(pointer)。在C++ 中,指针pointers 有其特定的优点,因此经常被使用。在后面我们将会看到这种变量如何被声明。


引用操作符Reference operator (*)

使用指针的时候,我们可以通过在指针标识的前面加星号asterisk (*)来存储该指针指向的变量所存储的数值,它可以被翻译为“所指向的数值”("value pointed by")。因此,仍用前面例子中的数值,如果我们写: beth = *ted; (我们可以读作:"beth 等与ted所指向的数值") beth 将会获得数值25,因为ted 是1776,而1776 所指向的数值为25。

指针的理解(转)

你必须清楚的区分ted 存储的是1776,但*ted (前面加asterisk * ) 指的是地址1776中存储的数值,即25。注意加或不加星号*的不同(下面代码中注释显示了如何读这两个不同的表达式):

beth = ted;  // beth 等于 ted ( 1776 )
beth = *ted;  // beth 等于 ted 所指向的数值 ( 25 )

地址或反引用操作符Operator of address or dereference (&)

它被用作一个变量前缀,可以被翻译为“…的地址”("address of"),因此:&variable1 可以被读作 variable1的地址("address of variable1" )。

引用操作符Operator of reference (*)

它表示要取的是表达式所表示的地址指向的内容。它可以被翻译为“…指向的数值” ("value pointed by")。

* mypointer 可以被读作 "mypointer指向的数值"。

继续使用上面开始的例子,看下面的代码:

andy = 25;
ted = &andy;

现在你应该可以清楚的看到以下等式全部成立:

andy == 25
&andy == 1776
ted == 1776
*ted == 25

第一个表达式很容易理解,因为我们有赋值语句andy=25;。第二个表达式使用了地址(或反引用)操作符(&) 来返回变量andy的地址,即 1776。第三个表达式很明显成立,因为第二个表达式为真,而我们给ted赋值的语句为ted = &andy;。第四个表达式使用了引用操作符 (*),相当于ted指向的地址中存储的数值,即25。

由此你也可以推断出,只要ted 所指向的地址中存储的数值不变,以下表达式也为真:

*ted == andy

声明指针型变量Declaring variables of type pointer

由于指针可以直接引用它所指向的数值,因此有必要在声明指针的时候指明它所指向的数据类型。指向一个整型int或浮点型float数据的指针与指向一个字符型char数据的指针并不相同。

因此,声明指针的格式如下:

type * pointer_name;

这里,type 是指针所指向的数据的类型,而不是指针自己的类型。例如:

int * number;
char * character;
float * greatnumber;

它们是3个指针的声明,每一个指针指向一种不同数据类型。这三个指针本身其实在内存中占用同样大小的内存空间(指针的大小取决于不同的操作系统),但它们所指向的数据是不同的类型,并占用不同大小的内存空间,一个是整型int,一个是字符型char ,还有一个是浮点型float。

需要强调的一点是,在指针声明时的星号asterisk (*) 仅表示这里声明的是一个指针,不要把它和前面我们用过的引用操作符混淆,虽然那也是写成一个星号 (*)。它们只是用同一符号表示的两个不同任务。

// my first pointer
#include <iostream.h>

int main ( ) {
int value1 = 5, value2 = 15;
int * mypointer;
mypointer = &value1;
*mypointer = 10;
mypointer = &value2;
*mypointer = 20;
cout << "value1==" << value1 << "/ value2==" << value2;
return 0;
}
value1==10 / value2==20

注意变量value1 和 value2 是怎样间接的被改变数值的。首先我们使用 ampersand sign (&) 将value1的地址赋给mypointer 。然后我们将10 赋给 mypointer所指向的数值,它其实指向value1的地址,因此,我们间接的修改了value1的数值。

为了让你了解在同一个程序中一个指针可以被用作不同的数值,我们在这个程序中用value2 和同一个指针重复了上面的过程。

下面是一个更复杂一些的例子:

// more pointers
#include <iostream.h>

int main () {
int value1 = 5, value2 = 15;
int *p1, *p2;
p1 = &value1; // p1 = address of value1
p2 = &value2; // p2 = address of value2
*p1 = 10; // value pointed by p1 = 10
*p2 = *p1; // value pointed by p2 = value pointed by p1
p1 = p2; // p1 = p2 (value of pointer copied)
*p1 = 20; // value pointed by p1 = 20
cout << "value1==" << value1 << "/ value2==" << value2;
return 0;
}
value1==10 / value2==20

上面每一行都有注释说明代码的意思:ampersand (&) 为"address of",asterisk (*) 为 "value pointed by"。注意有些包含p1 和p2 的表达式不带星号。加不加星号的含义十分不同:星号(*)后面跟指针名称表示指针所指向的地方,而指针名称不加星号(*)表示指针本身的数值,即它所指向的地方的地址。

另一个需要注意的地方是这一行:

int *p1, *p2;

声明了上例用到的两个指针,每个带一个星号(*),因为是这一行定义的所有指针都是整型int (而不是 int*)。原因是引用操作符(*) 的优先级顺序与类型声明的相同,因此,由于它们都是向右结合的操作,星号被优先计算。我们在 section 1.3: Operators中已经讨论过这些。注意在声明每一个指针的时候前面加上星号asterisk (*)。


指针和数组Pointers and arrays

数组的概念与指针的概念联系非常解密。其实数组的标识相当于它的第一个元素的地址,就像一个指针相当于它所指向的第一个元素的地址,因此其实它们是同一个东西。例如,假设我们有以下声明:

int numbers [20];
int * p;

下面的赋值为合法的:

p = numbers;

这里指针p 和numbers 是等价的,它们有相同的属性,唯一的不同是我们可以给指针p赋其它的数值,而numbers 总是指向被定义的20个整数组中的第一个。所以,p只是一个普通的指针变量,而与之不同,numbers 是一个指针常量(constant pointer),数组名的确是一个指针常量。因此虽然前面的赋值表达式是合法的,但下面的不是:

numbers = p;

因为numbers 是一个数组(指针常量),常量标识不可以被赋其它数值。

由于变量的特性,以下例子中所有包含指针的表达式都是合法的:

// more pointers
#include <iostream.h>

int main () {
int numbers[5];
int * p;
p = numbers;
*p = 10;
p++;
*p = 20;
p = &numbers[2];
*p = 30;
p = numbers + 3;
*p = 40;
p = numbers;
*(p+4) = 50;
for (int n=0; n<5; n++)
cout << numbers[n] << ", ";
return 0;
}
10, 20, 30, 40, 50,

在数组一章中我们使用了括号[]来指明我们要引用的数组元素的索引(index)。中括号[]也叫位移(offset)操作符,它相当于在指针中的地址上加上括号中的数字。例如,下面两个表达式互相等价:

a[5] = 0;  // a [offset of 5] = 0
*(a+5) = 0;  // pointed by (a+5) = 0

不管a 是一个指针还是一个数组名, 这两个表达式都是合法的。


指针初始化Pointer initialization

当声明一个指针的时候我们可能需要同时指定它们指向哪个变量,

int number;
int *tommy = &number;

这相当于:

int number;
int *tommy;
tommy = &number;

当给一个指针赋值的时候,我们总是赋给它一个地址值,而不是它所指向数据的值。你必须考虑到在声明一个指针的时候,星号 (*) 只是用来指明它是指针,而从不表示引用操作符reference operator (*)。记住,它们是两种不同操作,虽然它们写成同样的符号。因此,我们要注意不要将以上的代码与下面的代码混淆:

int number;
int *tommy;
*tommy = &number;

这些代码也没有什么实际意义。

在定义数组指针的时候,编译器允许我们在声明变量指针的同时对数组进行初始化,初始化的内容需要是常量,例如:

char * terry = "hello";

在这个例子中,内存中预留了存储"hello" 的空间,并且terry被赋予了向这个内存块的第一个字符(对应’h’)的指针。假设"hello"存储在地址1702,下图显示了上面的定义在内存中状态:

指针的理解(转)

这里需要强调,terry 存储的是数值1702 ,而不是'h' 或 "hello",虽然1702 指向这些字符。

指针terry 指向一个字符串,可以被当作数组一样使用(数组只是一个常量指针)。例如,如果我们的心情变了,而想把terry指向的内容中的字符'o' 变为符号'!' ,我们可以用以下两种方式的任何一种来实现:

terry[4] = '!';
*(terry+4) = '!';

记住写 terry[4] 与*(terry+4)是一样的,虽然第一种表达方式更常用一些。以上两个表达式都会实现以下改变:

指针的理解(转)

指针的数学运算Arithmetic of pointers

对指针进行数学运算与其他整型数据类型进行数学运算稍有不同。首先,对指针只有加法和减法运算,其它运算在指针世界里没有意义。但是指针的加法和减法的具体运算根据它所指向的数据的类型的大小的不同而有所不同。

我们知道不同的数据类型在内存中占用的存储空间是不一样的。例如,对于整型数据,字符char 占用1 的字节(1 byte),短整型short 占用2 个字节,长整型long 占用4个字节。

假设我们有3个指针:

char *mychar;
short *myshort;
long *mylong;

而且我们知道他们分别指向内存地址1000, 2000 和3000。

因此如果我们有以下代码:

mychar++;
myshort++;
mylong++;

就像你可能想到的,mychar的值将会变为1001。而myshort 的值将会变为2002,mylong的值将会变为3004。原因是当我们给指针加1时,我们实际是让该指针指向下一个与它被定义的数据类型的相同的元素。因此,它所指向的数据类型的长度字节数将会被加到指针的数值上。以上过程可以由下图表示:

指针的理解(转)

这一点对指针的加法和减法运算都适用。如果我们写以下代码,它们与上面例子的作用一抹一样: mychar = mychar + 1;

myshort = myshort + 1;
mylong = mylong + 1;

这里需要提醒你的是,递增 (++) 和递减 (--) 操作符比引用操作符reference operator (*)有更高的优先级,因此,以下的表达式有可能引起歧义:

*p++;
*p++ = *q++;

第一个表达式等同于*(p++) ,它所作的是增加p (它所指向的地址,而不是它存储的数值)。

在第二个表达式中,因为两个递增操作(++) 都是在整个表达式被计算之后进行而不是在之前,所以*q 的值首先被赋予*p ,然后q 和p 都增加1。它相当于:

*p = *q;
p++;
q++;

像通常一样,我们建议使用括号()以避免意想不到的结果。


指针的指针Pointers to pointers

C++ 允许使用指向指针的指针。要做到这一点,我们只需要在每一层引用之前加星号(*)即可:

char a;
char * b;
char ** c;
a = 'z';
b = &a;
c = &b;

假设随机选择内存地址为7230, 8092 和10502,以上例子可以用下图表示:

指针的理解(转)

(方框内为变量的内容;方框下面为内存地址)

这个例子中新的元素是变量c,关于它我们可以从3个方面来讨论,每一个方面对应了不同的数值:

c 是一个(char **)类型的变量,它的值是8092

*c 是一个(char*)类型的变量,它的值是7230

**c 是一个(char)类型的变量,它的值是'z'


空指针void pointers

指针void 是一种特殊类型的指针。void 指针可以指向任意类型的数据,可以是整数,浮点数甚至字符串。唯一个限制是被指向的数值不可以被直接引用(不可以对它们使用引用星号*),因为它的长度是不定的,因此,必须使用类型转换操作或赋值操作来把void 指针指向一个具体的数据类型。

它的应用之一是被用来给函数传递通用参数:

// integer increaser
#include <iostream.h>

void increase (void* data, int type) {
switch (type) {
case sizeof(char) : (*((char*)data))++; break;
case sizeof(short): (*((short*)data))++; break;
case sizeof(long) : (*((long*)data))++; break;
}
}

int main () {
char a = 5;
short b = 9;
long c = 12;
increase (&a,sizeof(a));
increase (&b,sizeof(b));
increase (&c,sizeof(c));
cout << (int) a << ", " << b << ", " << c;
return 0;
}
6, 10, 13

sizeof 是C++的一个操作符,用来返回其参数的长度字节数常量。例如,sizeof(char) 返回 1,因为 char 类型是1字节长数据类型。


函数指针Pointers to functions

C++ 允许对指向函数的指针进行操作。它最大的作用是把一个函数作为参数传递给另外一个函数。声明一个函数指针像声明一个函数原型一样,除了函数的名字需要被括在括号内并在前面加星号asterisk (*)。例如:

// pointer to functions
#include <iostream.h>

int addition (int a, int b) {
return (a+b);
}

int subtraction (int a, int b) {
return (a-b);
}

int (*minus)(int,int) = subtraction;
int operation (int x, int y, int (*functocall)(int,int)) {
int g;
g = (*functocall)(x,y);
return (g);
}

int main () {
int m,n;
m = operation (7, 5, addition);
n = operation (20, m, minus);
cout <
return 0;
}
8

在这个例子里, minus 是一个全局指针,指向一个有两个整型参数的函数,它被赋值指向函数subtraction,所有这些由一行代码实现:

int (* minus)(int,int) = subtraction;
指针的指针的地址,指针自身的地址,指针指向的地址理解 指针的指针,指针指向的地址,还有自身的地址之间的关系有些复杂,浅谈一下自己的理解。 #include <iostream> //#include <fstream> int test(int a, int b); int main() { using namespace std; int i = 1, j = 2; int* p1 = &i; int* p2 = &j; int** p3 = &p1; cout << "i的地址 阅读详情

相关推荐

模拟IC设计避坑:手把手教你用Cadence仿真恒定跨导轨到轨运放(附完整工艺库文件)

本文详细解析了使用Cadence仿真恒定跨导轨到轨运放的全流程,涵盖电路原理、工艺库配置、尺寸设计及仿真分析。通过1:3电流镜补偿技术实现跨导稳定,提供CSMC 0.25um工艺下的实战案例,帮助工程师规避设计陷阱,提升模拟IC设计效率。

weixin_30952535的博客 496

C++各种指针

一第一个指针例子 1代码 #include &lt;iostream&gt; using namespace std; int main() { int value1 = 5, value2 = 15; int *p1, *p2; p1 = &amp;value1; // p1 = address of value1 p2 = &amp;value2; /...

实践求真知 863

本地如何安装midscene.js运行环境

手把手教你本地安装midscene.js运行环境

实践助梦想成长 2608

c语言-指针

指针变量是变量,指针是地址。 指针的大小是固定的4/8个字节(32位平台/64位平台)。 指针是有类型,指针的类型决定了指针的±整数的步长,指针解引用操作的时候的权限。 指针字符指针数组指针指针数组数组传参和指针传参函数指针函数指针数组指向函数指针数组的指针回调函数指针和数组面试题的解析 字符指针 在指针的类型中我们知道有一种指针类型为字符指针 char* ; 一般使用: int main() { char ch = 'w'; char *pc = &ch; *pc = 'w'..

cckluv的博客 711

【基金量化研究系列】基金绩效归因模型——Brinson多期归因模型

文章目录1. 引言2. Brinson单期归因模型2.1 模型框架2.2 公式推导3. Brinson多期归因模型3.1 模型框架3.2 公式推导4. Brinson模型的应用场景4.1 基金组合归因4.2 基金经理能力刻画4.3 大类资产配置应用5. 模型的实现与实证案例研究写在最后 1. 引言 在 2. Brinson单期归因模型 2.1 模型框架 wp wb rp 组合收益:wp rp 择股收益:wb rp rb 择时收益:wp rb 基准收益:wb rb 2.2 公式推

Mikey_Sun的博客 1万+

湿敏电阻HR202的两种驱动方案实测:IO充放电法 vs. 交流方波ADC法,哪个更适合你?

本文深入评测湿敏电阻HR202的两种驱动方案:IO充放电法和交流方波ADC法。通过原理图分析、精度实测和资源占用对比,揭示交流方波ADC法在精度和稳定性上的优势,特别适合长期监测场景。同时提供IO充放电法在资源受限情况下的应用建议,帮助工程师根据项目需求做出最优选择。

weixin_30421809的博客 466

C++数组初始化

1. 数组的初始化规则 C++有几条关于初始化数组的规则,他们限制了初始化的时刻,决定了数组的元素数目与初始化器中值的数目不相同时将发生的情况。 只有在定义数组时才能使用初始化,此后就不能使用了,也不能将一个数组赋给另一个数组: int a[4] = { 1, 2, 3, 4}; // OK int b[4]; //OK b[4] = { 1, 2, 3, 4}; // 不合法 ...

Lee 2212

005、开关电源中的基本拓扑结构简介

本文介绍了开关电源设计中常见拓扑结构的特性与选型经验。文章从实际炸机案例入手,强调深入理解拓扑的重要性,详细分析了Buck、Boost、Buck-Boost等非隔离拓扑以及反激、正激、半桥、全桥、LLC等隔离拓扑的工作原理、设计要点和典型误区,重点指出各拓扑的电压/电流应力、效率瓶颈和常见设计错误。作者根据多年经验总结出不同功率等级和输入输出条件下的拓扑选型原则,并强调细节设计对成败的决定性影响。文章通过大量工程实例说明,正确的拓扑选择和参数计算是电源设计成功的基础,而忽略基础原理将导致反复修改甚至炸机风险

Jack010169的博客 225

初学C++。C++中float类型初始化(赋值)数据时,数据后面为什么要加f?

因为C++中float类型初始化(赋值)数据时,如果数据后面没有加f,系统会默认数据为double类型,当这个数据赋值给float类型时,系统会先把数据从double类型转换成float类型再把数据赋值给float类型定义的变量中。 如果你在数据的后面加上一个f时,系统默认为float类型,此时就不需要系统转换类型,可以直接赋值给float类型定义的变量中。从而减少一些不必要的工作,提高代码的质量和运行速度。 ...

qq_63852333的博客 6505

智能车图像处理22-进阶篇14--小s的判断

这篇文章中主要讲述智能车图像处理中 : 小s的判断方法。

taiyuezyh的博客 2571

Autosar MCAL-S32K324 Fls配置-基于EB

Autosar MCAL Flash配置,基于S32K324,EB软件

赞的博客 1516

C++中的数组初始化问题

动态数组初始化 使用new创建数组的时候,返回的是指向0号元素的指针 int nums1 = new int[10]{0,1};* //使用默认值初始化数组 ** int* nums2 = new int [10] ();** //前两个元素用给的值,其他的元素用int类型默认值 int nums3 = new int[10]{};* //使用默认值初始化数组 int nums4 = new in...

长期更新自学笔记 739

社区版 ABAP MCP 能不能读取 SAP S/4HANA 公有云开发对象,我的判断是能试,但不能当成已被 SAP 背书的标准通道

文章摘要:当前存在多个社区项目(如mcp-abap-adt、mcp-abap-abap-adt-api等)通过包装ABAP ADT能力为MCP Server,使AI开发工具能读取ABAP对象。这些项目技术上依赖ADT HTTP API或SAP官方ADT language server,但针对SAP S/4HANA Cloud Public Edition的完整适配仍存在挑战。SAP官方已通过VS Code扩展提供ADT MCP能力,而社区方案在云环境下需遵循ABAP Cloud的严格限制,仅能访问已授权的开

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 87

关于指向指针的指针的自我理解

关于指向指针的指针的自我理解 以下纯属个人看法,如有理解错误请各位大佬指正,谢谢! 话不多说直接上代码看注释!!! 代码. /---------关于指向指针的指针的自我理解---------*/ #include <stdio.h> int main(){ int num=123; int* p=&num; int** pp=&p; int*** ppp=&pp; printf("num=%d\n",num);//num是一个变量,

weixin_45715146的博客 377

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

理解一般指针和指向指针的指针

理解一般指针和指向指针的指针 在说指向指针的指针之前,不得不说指向变量的指针。先看如下示例: 1. 指向整型指针 先看如下示例: View Code  1 #include   2 using namespace std;  3   4 int main()  5 {  6     int a = 5;  7     int * p = &a;

g200407331的专栏 2万+

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

指针数组理解

指针数组理解 开发工具与关键技术:Visual Studio、C++ 作者:张国军 撰写时间:2019年05月06日 指针数组的元素类型是指针。 指针数组的元素存放对象的地址。 说明形式为:类型 * 标识符 [ 表达式 ] ; 先让我们来看一个实例,它用到了一个由 3 个整数组成的数组: #include using namespace std; const int MAX = 3; i...

weixin_44545509的博客 2190

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

多级指针的理解与运用

1.*(p+1) = p[1] 2.数组名也是首元素的地址,所以如果是一级指针数组,那么数组名就是二级指针(是一级指针的地址(指针)),同理,二级指针数组数组名就是三级指针。 3.三级指针解引用得到二级指针,二级指针解引用得到一级指针。

2302_80790488的博客 1841

指针理解,指针降级

指针就是指向一个特定内存地址的一个变量。简单的说可以理解为一个一维的线性空间,其中的每一个数对应一个存储单元,就是1个字节。指针有两个性质:指向性和偏移性。指向性指的是指针一定要有一个确定的指向,偏移性就是说指针可以加上一个数后偏移位置!指向别的存储空间。           指针的应用往往体现在数组,我们从数组开始解释指针的偏移。数组就是许多的变量,它的一个重要特征就是在内存空间中连续地存

小王的专栏 3391

对指针的一些理解

int a=4; int *p; p=&a; cout<<*p<<endl; 结果:4 这算简单的,我一开始也很明白 int* p是声明一个指针变量,那什么是指针变量,我的理解就是p是个变量,变量嘛就是可以变化的量,也就是说p里的值是可以变化的。 既然说*p 是去访问变量里的地址所存放的值(图中我没说清楚) 那 int * p 是什么意思呢? 刚开始的时...

programmer想玩潮 275

简单理解【指针数组】与【数组指针】

2024-07-22 笔记 - 4。

仟墨(郑龙浩)的博客 1253

对于指针的理解

目录 什么是指针/地址? 指针的常见类型: 常量指针: 指针变量的定义方法: 指针所需占用的空间 指针类型的意义: 地址有关常识 指针与数组 什么是指针/地址? 内存被划为很多格子(内存单元) 【】0 每个格子都有一个编号 【】1 32位指的是32根地址线—物理线-通电后有正负电-1/0 【】2...

Crossown的博客 659

这样子来理解C语言中指针的指针

友情提示:阅读本文前,请先参考我的之前的文章《从四个属性的角度来理解C语言的指针也许会更好理解》,若已阅读,请继续往下看。 我从4个属性的角度来总结了C语言中的指针概念。对于C语言的一个指针,比如int *p,4个属性分别如下: C语言指针p=(指针自己的值,与星号结合名,有用数据的值,有用数据的类型); 这4个属性用来理解C语言中单个指针可以,那么本篇再用这4个属性来解释C...

dichen3940的博客 592

如何理解指针?

1. 指针是内存中一个最小单元的编号,也就是地址2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量说白了,指针就是地址,地址又是数据,那么数据可以被保存在变量当中吗?答:当然可以,所以指针变量和指针不同。下面我会重点谈论他们之间的关系定义一个变量,本质是在内存中根据类型来进行开辟空间。指针变量就是存放地址的变量,任何指针变量的大小都是4个字节(32位机器)

xxxteb的博客 339

指针初阶理解

指针初阶理解 1.指针是什么 1.1理解内存 1.1.1 内存单元的概念 内存单元:内存被划分为一个个小的内存单元。 一个基本的内存单元的大小是一个字节 如图: 每个内存单元都有自己的编号,内存单元的编号可以快速定位到一个内存的单位。 1.1.2内存单元的编号是如何产生的呢? 32位机器——> 32根地址线——>通电——>高电频/低电频——>1/0 编号是由硬件电路直接产生的 00000000000000000000000000000000 … 11111111111111

simple_person的博客 2489
上一篇: 圆形碰撞算法
下一篇: Run loop和Thread
util_c
博客等级 码龄14年 35粉丝 41原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值