C语言高级

本文详细介绍了C语言中的指针概念,包括内存地址、指针定义、运算、与数组的关系,以及构造类型(如结构体、联合体、枚举)的使用。此外,还涵盖了动态内存管理、字符串函数和关键字const的理解。
摘要由CSDN通过智能技术生成

指针、构造类型、动态内1存管理、多文件与关键字

1、指针

内存地址:在内存空间中,对每一个字节都分配了一个唯一的编号,用于区别不同的位置。每个字节都有唯一的地址, 用来和内存中的其他字节相区别

指针:在内存空间申请空间来存储地址,叫做指针,也叫做指针变量

1、定义指针变量

指针变定义的形式:

数据类型 * 指针变量名;

数据类型:存储哪种类型数据的地址,指向哪种类型

指针变量:定义一个变量,于存储地址,如果要存储哪种类型的地址,数据类型就是

对应的类型

2、使用指针

存储地址:

指针变量 = 地址(要求地址的空间能够使用)

对于变量的地址:通过&(取地址运算符)

指针 = &变量

操作对应地址的数据:通过地址的方式访问

数据用变量名来表示代表变量中的值。也可以通过指针来访问变量,指针对所指变量的访问采用间接访问运算符*

用指针来访问变量:

*指针名 访问对应地址(指针名存储的地址)的数据空间

野指针:

指针记录的地址不明确(存储的地址不知道,或地址对应空间是否具有操作权限不确定),这种指针叫做野指针

野指针不要直接进行 取*

空指针:

指针记录的地址是NULL(地址: 0x00), 系统规定NULL地址不允许进行操作只要操作就会报错

万能指针:

void * 类型指针变量,可以存储任意类型的地址,也可以把指针赋值给其他的任意类型指针变量

void 指针,指针存储地址,不能进行取值操作(取*),因指向地址不明确

指针变量的初始化:

在定义指针变量时,进行赋值,就叫做初始化

类型*指针名=地址;

3、指针的运算

+:

指针 + n

把指针地址往增大方向移动整数个指针指向类型(存储当前指针的类型)的大小*整数大小

指针 + n=指针 + n*sizeof(指向类型)

int *p; p+5;//往地址增大方向移动5*4

-:

指针 - 整数

把指针地址往减小方向移动整数个指针指向类型(存储当前指针的类型)的大小*整数大小

指针 - 整数*sizeof(指向类型)

指针++:

先使用指针,然后 指针 = 指针 + 1

++指针:

先 指针 = 指针 + 1,然后 使用指针

指针--:

先使用指针,然后 指针 = 指针 - 1

--指针:

先 指针 = 指针 - 1,然后 使用指针

指针 - 指针:

获取两个指针之间间隔多少个对应类型的数数据

(指针 - 指针)/sizeof(指向类型)

4、指针与一维数组

一维数组是一 段连续的空间存储多 个数据元素,在数组中相邻的元素, 间隔大小为每个元素类型的大小,即 数组名[ 元素i ]==数组名[ 元素i-1 ] + 类型大小

指针能够进行运算,指针 + 1,移动一个数据类型的大小,即 指针 + 1==指针+指向类型大小

如果指针变量存储了数组的元素地址,指针+1,就是数组中下一个元素的地址,可以通过指针访问整个数组

只要知道数组的起始地址(第零个元素的地址),就可以遍历整个数组

数组首地址:数组的起始地址,就是第零个元素的地址

在数组中,数组名就表示数组的首地址

数组首地址(数组名) + n:偏移n个数据元素大小

*(数组名 + n)==数组名[ n ]

因为数组名可以表示数组首地址,而指针变量也可以存储数组首地址,在访问数组的操作时,指针变量和数组名作用一致,所以

数组名[n]:访问数组的n元素====指针名[n]

5、字符串与字符数组

字符串:够个字符组成-一个连续且有序的字符序列

"abedef"-----字符串

C程序中,通过字符数组来存储字符串

字符数组通过访问数组中的元素,就是访问字符串

如果需要整体访问字符数组中存储的字符串,要求在字符串结束的下一个字符位置存储"\0"

字符数组存储字符串:

字符数组初始化存储字符串【注意通常,在进行输入前把数组初始化'\0'】

char 数组名[ 长度 ] = "字符串";【默认字符串后自动加“\0”,赋值初始化可不写长度】

输入字符串到字符数组中

scanf("%s",数组名);

输出打印字符数组中的字符串

printf("%s",数组名);

常量字符串表示:

“abcde”---------常量字符串

在常量字符串中,在最后字符后默认包含”\0“字符

在程序中如果写出常量字符串,则常量字符串表示常量字符串的首地址(第零个字符地址)

如:“abccde",得到就是字符串的首地址

地址,指针类型,都是统一的大小,各个类型之间没有区别

32位机器: 4B

64位机器: 8B

6、指针与二维数组

二维数组:

二维数组中,每个元素是一个维数组,在元素(一维数组)中,每个成员就是一个值

数据类型 数组名 [ 行 ][ 列 ]

对于二维数组而言,数组名是整个二维数组的首地址,第零个元素的地址,二维数组的元素都是一维数组,即二维数组数组名表示其中元素,整个维数组的地址。

int a[3][4];

a == &a[];//a[0]是整个-维数组

由于a表示整个元素的地址(一维数组的地址),所以进行指针运算时,+1,加上整个一维数组大小

a: &a[0],第零个一维数组的地址

a+1: &a[1],第一 个一维数组的地址

a+2: &a[2],第二 个一维数组的地址

a[0]:示二维数组的元素零,第零个一维数组, a[0]是一 维数组的数组名,在这个维数‘组的首地址

a[0]==&a[0][0]

&a[0][1]==a[0]+1

*(a+1)==&a[1][0]

注意:

a+1,表示移动二维数组的一个元素(一维数组)大小

a[0]+1,表示移动一维数组的一个元素(数据类型值)大小

数组指针:

是一个指针,指针用于存储整个数组的地址,指针的指向类型为数组

定义:

指针类型 (* 指针变量名)[大小]

数组指针和二维数组名等价的,因为二维数组表示第零个元愫(一维数组) 的地址

7、多级指针与指针数组

指针数组:

是一个数组,只是每一个元素都为指针类型

定义格式:

指向类型 *指针数组名[元素个数]

例:

int *p[5] 义包含5个元素每个元素为指针(int *)

int a;

p[2]=&a;

多级指针:

一级指针:存储变量的地址

二级指针:存储一级指针的地址

三级指针:存储二级指针的地址

……

8、指针与函数

指针作为函数的参数:

使用函数时,把地址作为参数进行传递

返回值类型函数名(指针参数1,指针参数2);接受传递的是地址

调用:

函数名(地址,地址/指针);

如果是数组作为形式参数,会由编译器自动变为对应类型指针

如:

int sumarray(int p[10]int length) p就是指针int*.

函数指针:指针存储的是函数的地址

函数指针表示:

返回值类型

(*指针变名) (参数1,参数2,参数.....)

函数地址:

函数名就是用于表示函数的地址

函数指针=函数名;

调用函数:

通过函数指针进行调用

函数指针名(实参);

指针类型 * 指针变量名

2、结构类型

由于基本数据类型不能满足需要,需要把多个单-的数据类型进行组合,共同表示新的复合数据,形成新的类型,叫做构造类型

1、 结构体

使用多种数据类型作为成员,进行组合,构成新的类型,叫做结构体

声明结构体:

struct 结构体名

{

类型1 成员1;

类型2 成员2;

类型3 成员3;

……

};//在程序中添加一种新的类型,不占用内存空间,只是说明在程序中有一种新的类型

定义结构体变量:

struct 结构体名字 变量名;

对结构体变量的操作,就是对结构体变量的成员进行操作

结构体变量访问成员:

结构体变量名 . 成员名;

结构体变量初始化:

在定义结构体变量时,对其中的所有成员进行操作

顺序对成员进行初始化:

struct 结构体名 变量名 = {成员1值,成员2名,成员3名,……};

如:

部分初始化://未初始化部分为0

struct 结构体名 变量名 = {成员2名=成员值,成员3名=成员值,……};

结构体指针如何访问变量的成员:

结构体指针:

struct 结构体名 * 指针名 = 结构体地址

访问方式:

指针-->成员://访问结构体指针对应地址中的成员

(*指针).成员

结构体特殊的声明方式:

struct

{

类型1 成员1;

类型2 成员2;

类型3 成员3;

……

}结构体变名; //在声明时同时定义结构体变量,但是之后不能使用这个声明进行定义变量

2、共同体(联合体)

使用多种数据类型作为成员,进行组合,但是使用同-段空间存储(多个成员共用一个空间),构成的新的类型,就叫做共用体

使用共用体的问题:同一时刻只能操作一个成员

声明共用体类型:

union 共用体名

{

类型1 成员1;

类型2 成员2;

类型3 成员3;

……

};

用法://共用体与结构体一致

3、枚举

枚举是定义一种新类型时,这个类型能够取值的范围是确定的,通过这个定义的新类型把能够取值的范围一一列举出来,这种类型叫做枚举

声明枚举类型:

enum 枚举名

{

成员1,

成员2,

成员3,

……

};

枚举类型中,每个成员就代表能够取的一个值

声明类型时,如果成员没有赋值,成员就等于上一个成员的值+1,如果成员1没有赋值则为0

定义枚举变量: .

enum 枚举名变量名;

变量名=成员;

3、字符串函数

#include<string.h>

//把src首地址的字符串,拷贝到dest首地址中
char *strcpy(char *dest,const char *src);
//把src首地址的字符串前n个,拷贝到dest首地址中
char *strncpy(char *dest, const char *src, size_t n);

//比较字符串s1和s2是否相等,如果相等返回0,如果不等返回当前字符的差值
int strcmp(const char *s1,const char *s2);
//比较字符串s1和s2的 前n 个字符 是否相等,如果相等返回0,如果不等返回当前字符的差值
int strncmp(const char *s1,const char *s2, size_t n);

//计算s字符串的字符个数(不算'\0'),返回值就是字符串的长度
size_t strlen(const char *s);

//把src字符串拼接到dest字符串后;
char *strcat(char *dest, const char *src);
//把src字符串前n个字符拼接到dest字符串后
char *strncat(char *dest, const char *src, size_t n);

4、动态内存

栈中变量,只要离开了变量的生命周期,变量就会由系统销毁释放

堆空间:有程序员在程序中,自己进行管理的空间,需要使用时进行申请,自己进行释放销毁。空间的申请与释放由程序员在程序中指定,叫做动态内存

申请空间:

#include <stdlib.h>
ma1loc函数在堆空间中申请指定大小的内存空间
void *malloc(size_t size);
参数:
    size_t size:要申请的字节数
返回值:
    void *:如果申请成功,返回申请空间的首地址
            如果申请失败,返回NULL    地址

释放空间:

#include <stdlib.h>
free就是释放malloc申请的空间
void free(void *ptr);
参数:
    void *ptr:
申请空间的首地址,进行释放空间

5、关键字

const:

        在定义变量时,使用const关键字修饰,当前变不可修改,作用类似于常量

        const 数据类型 变量名

        通常情况下const变量要进行初始化

                const修饰指针变量时,不同的用法:

        指向类型 * const 指针变量名;

        表示指针变量不可修改,但是指向地址中的内容可以修改

        指针变量不可改;

        但 *指针变量的可以改

        指向类型 const * 指针变量名; / const 指向类型 * 指针变量名;

        表示指针变量不可修改,但是指向地址中的内容可以不可修改

        指针变量可改;

        但 *指针变量不可以改

        const 指向类型 * const 指针变量名;

        指针变量不可改;

        *指针变量不可以改

        static

                修饰局部变量

                修饰全局变量

        auto

                自动类型,定义在栈中,由系统进行管理

        register

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值