c语言指针

C语言指针相关解析

匿名 (未验证) 提交于 2019-12-03 00:19:01
在C语言中除了一级指针和二级指针,还有一些比较常用但又比较拗口的指针类型。 比如:指针数组和数组指针。它们的名称只是前后顺序不一样,却有着千差万别,容我向大家徐徐道来。 先看两种定义:int *p[5], int(*p)[5]。 第一个是指针数组,由于"[ ]"的优先级高于“*”,所以p先和"[ ]"结合,构成了数组,后和"*"结合,成了指针数组。 指针数组依然是数组,只不过它里面存放的是指针。如图: 第二个是数组指针,在加了“()”后,p先与“*”结合,因此成为了数组指针。顾名思义,它是一个指针,指向p[4]数组 的首地址。 继续如图!: 函数指针:例如void(*fun1)( );函数指针是用来存放函数地址的变量,在函数中,函数的地址是入口地址,由函数名来表示。 函数指针比较好理解,因此不会赘言太多。 在函数指针的基础上,介绍一个定义: 函数指针数组,它是一个数组,用来存放一组函数的地址。 函数指针数组的一个简单应用:计算器 int (* p )[ 5 ]( int x , int y )={ 0 , add , sub , mul , div }; 其中int(*p)[5]()就是一个函数指针数组,这样调用函数时,特别方便,效率也高。 在函数指针数组的概念下,最后介绍一个顺口溜一般的类型: 函数指针数组的指针。它是一个指针,指向一个数组,数组里面存放函数的地址。 依次拆开

C语言之复杂指针简析

匿名 (未验证) 提交于 2019-12-03 00:18:01
指针数组 :首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身决定。它是“储存指针的数组”的简称。 数组指针 :首先它是一个指针,它指向一个数组。在 32 位系统下永远是占 4 个字节,至于它指向的数组占多少字节,不知道。它是“指向数组的指针”的简称。 那么下边俩个分别叫做什么呢? int *p1[4]; int (*p2)[4]; 第一个我们称之为指针数组。“[ ]”的优先级比“ ”要高。p1 先与“[ ]”结合,构成一个数组的定义,数组名为 p1,int 修饰的是数组的内容,即数组的每个元素。这是一个数组,其包含 4 个指向 int 类型数据的指针,即指针数组。 我们可以这样理解: 第二个我们称之为数组指针。在这里“()”的优先级比“ []”高,“*”号和 p2 构成一个指针的定义,指针变量名为 p2,int 修饰的是数组的内容,即数组的每个元素。数组在这里并没有名字,是个匿名数组。那现在我们清楚 p2 是一个指 针,它指向一个包含 10 个 int 类型数据的数组,即数组指针。 同样,也可以这样理解: 函数指针 :就是函数的指针。它是一个指针,指向一个函数。 函数指针数组 :它是一个数组,数组内存储了指向函数的指针。 函数指针数组指针 :它是一个指针,只不过这个指针指向一个数组,这个数组里面存的都是指向函数的指针。 看如下例子: char * ( pf)

C++primer学习笔记(三)

匿名 (未验证) 提交于 2019-12-03 00:11:01
没啥好说的,就是+- /& =、==等。 简单归纳:当一个对象被用作右值的时候,用的是对象的值(内存);当对象被用作左值的时候,用的是对象的身份(在内存中的位置)。假设p的类型是一个int*,则decltype如果作用于一个表达式时如decltype(*p)得到的是一个引用类型,而decltype(&p)的结果是一个int ** 其中逻辑与运算符(&&)和逻辑或(||)运算符是短路求值运算符: 对于逻辑与运算符来说,当且仅当左侧运算对象为真时才对右侧运算对象求值。 对于逻辑或运算符来说,当且仅当左侧运算对象为假时才对右侧运算对象求值。 赋值运算符满足右结合律,即 1 2 int a,b,c; a = b = c =3;//可以连续赋值 赋值运算优先级较低,所以在条件语句中,赋值部分通常加上括号,如: cpp int i; while((i=get_value())!=42){ //anything } 分前置版本和后置版本。前置版本先加1,然后将改变后的对象作为求值结果,后置版本也会将运算对象加1,但是求值结果是运算对象改变之前那个值的副本。 如果想测试一个算术对象或者指针对象的真值,最直接的方法就是将其作为if条件 1 2 3 4 if(val);//如果val是任意的非0值,条件为真 if(!val);//如果val是0,条件为真 有时我们试图将上面的真值测试写成如下形式:

C++传值和传引用

匿名 (未验证) 提交于 2019-12-03 00:08:02
首先你肯定明白一个道理:当初始化一个非引用类型的变量时,初始值被拷贝给变量,此时对变量的改动不会涌向初始值 int n = 0 ; int i = 1 ; // i是n的副本 i = 42 ; // i的值改变,n的值不改变 传值参数的机理完全一样,由于 每次调用函数时都会重新创建它的形参,并用传入的实参对形参进行初始化 ,所以 函数对形参做的所有操作不会影响实参 ,如果我们想让函数改变我们传入的实参本身们就可以用到 指针形参 访问函数外部对象 先看一段代码: int n = 0 ; int i = 1 ; int * p1 = & n ; //p1指向n int * p2 = & i ; //p2指向i * p1 = 42 ; //n的值改变,p1不变 p1 = p2 //现在p1指向了i,但是i和n的值都不变 当执行指针拷贝操作时,拷贝的是指针的值(地址),拷贝之后,两个指针是不同的指针,因为指针可以使我们间接地访问所指向的对象,所以通过指针可以修改对象的值 指针形参也差不都 // 接受一个int类型的指针,然后将指针所指向的对象置0 void reset ( int * ip ) { * ip = 0 ; // 改变指针ip所指向对象的值 ip = 0 ; // 只改变了ip的局部拷贝,实参未被改变 } void reset ( int i ) { i = 0 ; } int

字符串、字符和字节

匿名 (未验证) 提交于 2019-12-03 00:05:01
C语言中没有显示的字符串数据类型,字符串以字符串常量或者字符数组的形式出现,字符串常量适用于那些程序不会对它们进行修改的字符串。所有其它字符串都必须存储于字符数组或动态分配的内存中。 字符串 是一串零个或多个字符,并且以一个位模式为全0的NULL字节结尾。 字符串所包含的的字符内部不能出现NULL字节。 NULL字节是字符串的终结符,但它并不是字符串的一部分,所以字符串的长度并不包含NULL字节。 字符串函数的声明都在 string.h 头文件中。 字符串的长度就是它所包含的字符个数,通常使用函数 strlen 来计算字符串的长度。 sizet_t strlen ( char const * string ); size_t 定义在 stddef.h 中,它是一个无符号整数类型。 在表达式中使用无符号数可能导致不必要的结果,如下: if ( strlen ( x ) >= strlen ( y ))... if ( strlen ( x ) - strlen ( y ) >= 0 )... 第二条语句的结果永远为真,因为strlen(x)、strlen(y)的返回值都是无符号数,所以>=左边是无符号数,无符号数不可能小于零。 最常用的字符串函数都是不受限制的,就是说它们只是通过寻找字符串参数结尾的NULL来判断它的长度。在使用这些函数时,必须要 保证结果字符串不会溢出内存。

C++通过函数指针调用类的私有方法

匿名 (未验证) 提交于 2019-12-03 00:03:02
1 前言 今天突发奇想,能否通过函数指针调用类的私有方法。即将私有方法的指针通过公有方法传出来,实现在类外调用类的私有方法。但是实现过程还是一波三折,将过程记录下来,防止踩坑。 2 实现 2.1 C中的方法 在C语言中,我们可以使用如下方式来获取函数指针,并返回: typedef void (*Func)(); void func1() { std::cout << "hello world" << endl; } Func getFunc() { return func1; } 但是当我们在 C++ 中直接像 C 那样使用类的成员函数指针时,通常会报错,提示你不能使用非静态的函数指针: reference to non-static member function must be called 解决办法有两个: 把非静态的成员方法改成静态的成员方法 正确的使用类成员函数指针(在下面介绍) 2.2 C++中访问成员函数指针 将函数改为静态函数很简单, 只需在函数声明前加上 static 关键字即可。 但是C++中类成员函数指针的引用方式需要一些技巧: 声明 :与普通函数作为区分,指向类的成员函数的指针只需要在指针前加上类类型即可,格式为: typedef 返回值 (类名::*指针类型名)(参数列表); 需要注意的是指针符号 * 必须写在指针类型名的前面,不要写在类名的前面。 赋值

c语言单向链表

匿名 (未验证) 提交于 2019-12-02 23:57:01
一、链表概述     链表是一种常见的重要的数据结构。它是动态地进行存储分配的一种结构。它可以根据需要开辟内存单元。链表有一个“头指针”变量,以head表示,它存放一个地址。该地址指向一个元素。链表中每一个元素称为“结点”,每个结点都应包括两个部分:一为用户需要用的实际数据,二为下一个结点的地址。因此,head指向第一个元素:第一个元素又指向第二个元素;……,直到最后一个元素,该元素不再指向其它元素,它称为“表尾”,它的地址部分放一个“NULL”(表示“空地址”),链表到此结束。 二、链表创建、删除、插入等如下,将函数与声明定义进行分离为.h和.c: 2.1 linklist.h 1 #pragma once 2 typedef struct list 3 { 4 int data;//数据域 5 struct list *next;//指针域 6 }LinkList; 7 LinkList *crate_list(); //建立一个节点 8 void traverse(LinkList*ls);//循环遍历链表 9 LinkList* insert_list(LinkList* ls, int n, int data);//在指定位置插入元素 10 int delete_list(LinkList* ls, int n);//删除指定位置元素 11 int count_list

C语言的内存管理

匿名 (未验证) 提交于 2019-12-02 23:52:01
堆和栈的区别: 栈的特征 执行的速度相对较快; 空间较小; 生存期由系统决定; 作用域较小; 有名空间,可以通过变量名或者数据名访问; 堆的特征 执行的速度相对较慢; 空间较大; 生存期由“自己”决定,malloc申请,free释放; 作用域很大(整个程序都可以访问); 无名空间,只能通过指针使用; C语言空间的申请 malloc 功能: 分配 size 字节的未初始化内存。若分配成功,则返回指向分配内存块最低位(首位)字节的,为任何拥有基础对齐的对象类型对齐的指针。 头文件: #include<stdlib.h> 原型: void* malloc( size_t size ); 参数: size - 要分配的字节数 返回值: 成功时:返回指向新分配内存的指针。为避免内存泄漏,必须用 free() 或 realloc() 解分配返回的指针。 失败时:返回空指针。 说明: malloc申请的空间为连续空间;malloc申请的是没有初始化的空间; 返回值类型是void * 该类型表明malloc返回的地址空间中的数据类型是不确定,必须经过强制类型转换才可以使用。 realloc 功能: 先判断当前的指针是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间

C语言讲义――指针(pointer)

匿名 (未验证) 提交于 2019-12-02 23:49:02
指针是C语言最重要的特性之一, 也是最容易被误解的特性之一。 现代计算机把内存分割为字节(Byte), 每个字节都有唯一的地址(Address), 如果内存中有n个字节,可以把地址看做0~n-1的数。 程序中的每个变量都占据字节(至少1字节),把第一个字节的地址称为”变量的地址”, 假设变量int i占有内存2000~2003,则变量i的地址是2000。 口诀: 变量有位置,位置有地址 指针是变量,其值为地址 指针就是地址,指针变量就是存储地址的变量。 C语言要求每个指针变量只能指向一种特定的类型的对象。 int *p; double *q; char *r; 指针变量的赋值: int i=2099; int* p; P = &i; printf("%d", *p); &取地址运算符 *间接寻址运算符 下例中: i是普通变量,&i是存储变量的地址 p是指针,是地址,*p是指针指向地址的值 #include <stdio.h> main() { int i=2099; printf("变量的值:%d\n", i ); printf("变量的地址:%x\n", &i ); int *p; p = &i; printf("指针(值):%d\n", *p ); printf("指针(地址):%x\n", p ); } 在变量声明时,如果没有确切的地址可赋值

c语言-数组学习总结(3)

匿名 (未验证) 提交于 2019-12-02 23:43:01
数组,指针与函数 指针与数组 数组中几个关键符号(a、a[0]、&a、&a[0])的理解 数组与指针的关系 函数、数组和指针 指针操作 指针与数组 数组名:数组名表示数组的首元素首地址,因此作右值可以直接赋值给指针。 如果有 int a[5]; 则 a和&a[0]都表示数组 首元素a[0]的首地址。(指向首元素) 而&a则表示 数组的首地址。(指向整个数组) 数组中几个关键符号(a、a[0]、&a、&a[0])的理解 结合左值右值去理解(前提是 int a[10]) (1) a不能做左值 (因为数组在初始化之后就不能进行整体操作了),做右值表示首元素的首地址等同于&a[0] (2)a[0]做左值时表示数组第0个元素对应的内存空间;做右值时表示数组第0个元素的值 (3)&a不能做左值;&a做右值时表示整个数组的首地址。 (4)&a[0]不能做左值,做右值时表示首元素的首地址等同于a。 数组与指针的关系 dates+2==&date[2]; //相同的地址 *(dates+2)==dates[2]; //相同的值 以上表明可以的使用指针标识数组的元素和获得元素的值。 定义ar[n]的意思是*(ar+n),可以认为*(ar+n)的意思是“到内存的ar位置,然后移动n个单元,检索存储在那里的值”。 ==另外,还要区别*(dates+2)和*dates+ *( dates+2) /