C语言知识总结(建议收藏)(下)

简介: 指针:指针变量,它指向内存中的一块地址 -- 存储一个地址编号 - 指向对象的类型 - 指向的空间的大小

六、指针

1.定义?什么是地址?什么是空间?

指针:指针变量,它指向内存中的一块地址--存储一个地址编号- 指向对象的类型-指向的空间的大小

地址:内存中会按照字节进行编号,字节在内存中编号

空间:从这个地址编号开始,存放对象数据类型个字节大小的空间。

2.定义指针的格式是什么?

指向对象的数据类型 *指针变量名;

3.如何分析一个指针?指针指向的对象可以是什么数据类型?

指针分析的三要素:

①指针变量名

②变量名的类型

除了变量名以外的内容就是变量名的类型

③指向对象的类型

除了*变量名以外的内容就是指向对象类型

4.如何通过指针名对指针指向空间进行读写操作?

*指针名 代表的是指针指向的空间

读操作:*指针名

写操作:*指针名 =

5.如何改变指针的指向

给指针赋值

Int a = 30,b = 50;

Int *p = &a;

p = &b;

6. 指针变量空间大小是多少?指向不同数据类型的指针数据大小是一样的吗?为什么?

4 个字节

指针变量所占的字节数和指针指向对象的数据类型无关。

因为指针存储的是变量的地址,是一个 8 位十六进制数,从 00000000~ffffffff,

ffff ffff=16^8=2^4^8=2^32b=2^22kb=2^12mb=2^2gb=4gb

00000000~ffffffff 可以表达 4gb 内存大小的地址编号,对于运行内存来说足够了

7. 指针偏移如何计算?和什么有关?

指针的偏移跟 指向对象的数据类型 有关。

指针偏移 是以 指向对象的数据类型所占字节数为 单位进行偏移的

例如:

int *p

指针跳动一步,指针变量里存储的 地址编号就偏移 4

//p 的值 +4

char *p

指针跳动一步,指针变量里存储的 地址编号就偏移 1

//p 的值 +1

short *p

指针跳动一步,指针变量里存储的 地址编号就偏移 2

//p 的值 +2

指针可以和整数进行加法操作

指针可以和整数进行减法操作

指针可以和指针进行减法操作 - 得到的结果为:相差的单位数

8. 定义一个指向有 10 int 型数据的数组首元素的指针

int a[10];
int *p=a;

9. 定义一个指向一个指向用户姓名的指针

Char username[] = “liming”
Char *str = username

10. 指针直接指向一个常量字符串和指针指向一个盛放字符串的数组有什么区别?

指针指向一个常量字符串是不允许通过指针对字符串进行部分修改的,因为它是一个常量

指针指向一个盛放字符串的数组,那么可以对数组中的字符进行修改操作

11. 什么是数组指针?如何定义?


一个指针,指向的对象是一个一维数组(注意他不是数组找个某个元素,而是数组这个整体)
数据的类型(
* 指针名) [ 元素的数据个数 ] ;
Int (*p)[3] = {{1,2,3},{4,5,6}}


12. 通过数组指针访问数组中的元素?

*(* (指针名 + 二维数组元素的偏移量) + 某个元素的数据的偏移量 )
Int (*p)[3] = {{1,2,3},{4,5,6}}
4:*(*(p+1)+0)
5:*(*(p+1)+1)
p 指针指向的对象是: int [3], 因此一次偏移偏移一个 int [3]

13. 什么是指针数组?如何定义?

如果一个数组中的所有元素保存的都是指针,那么我们就称它为指针数组。

数据类型
* 数组名 [ 元素个数 ] ;
或者 数据类型
*( 数组名 [ 元素个数 ]);
int a = 20,b = 30;
Int *p[3] = {&a,&b};

14. 如何通过指针数组取访问数据?

Int *p[3] = {&a,&b};
a:*(p[0]) 或者 *(*(p+0))
b:*(p[1]) 或者 *(*(p+1))
先考虑数组然后再考虑指针

15. 指针在函数中有哪些应用?

指针作为函数形参-集合类型传参

指针作为函数返回值-指针函数(一个函数返回值是一个指针)

个指针指向一个函数,调用-函数指针

16. 什么是指针函数?哪些类型可以作为指针函数的返回值类型?

C 语言允许函数的返回值是一个指针(地址),我们将这样的函数称为指针函数。

定义:

数据类型 * 函数名 ( 函数的形参 )
{
函数体
return 指针 ;
}
C 语言里面的数据类型都可以作为指针函数的返回值类型

17. 什么是函数指针?如何定义?如何调用?应用场景是?

一个指针指向一个函数,通过指针进行函数的调用。

定义:

函数返回值类型 (* 指针名 )( 形参列表 )
void (*mm)(void);

使用:

①定义一个函数指针

确定指向对象(函数) 的 返回值类型

参数类型

②将要指向的函数的地址(函数名)赋值给指针变量

③调用: (* 指针变量名 ) (实参) ;

使用场景:函数作为形参传递,比如:回调函数等

18. 如何定义一个二级指针?二级指针和一级指针的区别是什么?

如果一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针。

C 语言不限制指针的级数,每增加一级指针,在定义指针变量时就得增加一个星号*

指向的对象的数据类型(指针类型) *二级指针名;

Int a = 20;
Int *p = &a;
Int **q = &p; // q 为二级指针,它的指向对象是 int *
一级指针里面保存的数据的地址,二级指针里面保存的是一级指针的地址

19. 如何通过一个二级指针,获取到变量空间的数据值?

**指针名

**q 为二级指针指向的一级指针指向的空间,通过它可以对该空间进行读写操作。

20. NULL void *的区别是什么?

NULL 零值、等于零的意思,在 C 语言中表示空指针。

NULL 是在 stdio.h 中定义的一个宏,它的具体内容为:

#define NULL ((void *)0)

NULL 指向了地址为 0 的内存,在进程的虚拟地址空间中,最低地址处有一段内存区域被称为保留区,

这个区域不存储有效数据,也不能被用户程序访问,将 NULL 指向这块区域很容易检测到违规指针。

void * 表示一个有效指针,它确实指向实实在在的数据,只是数据的类型尚未确定,在后续使用过程中

一般要进行强制类型转换。

比如: C 语言动态内存分配函数 malloc() 的返回值就是 void * 类型,在使用时要进行强制类型转换。

七、结构体

1.结构体用来解决什么问题?

将多个不同类型的数据放在一起,形成一个整体,类似面向对象中的类

2. 结构体定义的格式?结构体类型的成员可以是什么类型?

struct
结构体名
{
成员数据类型 1 成员名 1;
成员数据类型 2 成员名 2;
成员数据类型 3 成员名 3;
成员数据类型 4 成员名 4;
};
结构体成员可以是 c 语言的任意一种数据类型。

3. 使用结构体类型定义变量的格式?

struct

结构体名 变量名;

结构体别名 变量名;

4. 结构体变量访问成员的方式?

结构体变量.成员名

5. 结构体变量或者结构体类型所占空间大小如何计算?

Sizeof(结构体类型) 或者 sizeof(结构体变量)

6. 什么是字节对齐,有什么规则?

结构体中的成员在内存中是按字节对齐的方式存储的!

规则为:

1 、找到结构中占用空间最大的数据类型 -max 个字节

2 、以 max 个字节为单位分配空间

3 、每个成员按照顺序分配内存,内存不够再以 max 字节为单位进行分配

4 、每个成员距离结构体的首地址之间的距离必须是成员本身所占字节数的整数倍

5、结构体类型所占空间为上述分配空间之和

7. 如何将一个结构体变量里面的内容赋值到另外一个结构体变量中?

结构体变量可以直接复制,复制相当于拷贝一份数据放入变量名 2 的相应的空间中。

Struct 结构体名 变量名 1 = {........};
Struct 结构体名 变量名 2 = 变量名 1 ;

8. 结构体指针访问指向的对象的成员如何访问?

结构体指针名->成员名

9. 如何定义一个结构体数组?如何访问结构体数组中的元素?

Struct 结构体名 数组名[元素个数]

通过数组下标访问结构体数组中的结构体

八、共用体

1.定义

多个成员共用同一块内存

2. 共用体变量如何声明?如何确定共用体变量或者共用体类型所占的字节数?

union 共用体名
{
成员类型 成员名;
......
}
共用体类型: union 共用体名
共用体所占字节数取成员中占用字节数最大的值,可以使用 sizeof(union 共用体名 )

3. 共用体的应用场景有哪些?

大小端判断,方便通信传输中的 float 类型数据传递

4. 什么是大小端?为什么有大小端之分?

大端模式(Big-endian),是指数据的高字节,保存在内存的低地址中,而数据的低字节,保存在内存 的高地址中;

小端模式( Little-endian ),是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的 低地址中.

在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为 8bit 。但是在C 语言中除了 8bit 的 char 之外,还有 16bit 的 short 型,32bit 的 long 型(要看具体的编译器),另外对于位数大于 8 位的处理器,例如 16 位或者 32 位的处理器,由于寄存器宽度大于一个字节,那么必 然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。

我们常用的 X86 结构是小端模式,而 KEIL C51 则为大端模式,很多的 ARM , DSP 都为小端模式。

九、枚举

1.枚举用来解决什么问题?有什么好处?

程序用枚举方法列举一组 标识符 作为枚举类型的 值 的 集合,增强代码的可阅读型。

2. 枚举的标识符是一个整型数据吗?有什么样的取值规则?

标识符是一个整型数据,可以直接使用,取值如果没有默认值采用从 0 开始一次增 1 计数,如果有默认

值使用默认值,其后的标识符的值看离他最近的标识符的值上增 1.

3. 如何定义一个枚举变量,如何给枚举变量赋值?

枚举类型 变量名 ;
枚举类型变量赋值等同于整型变量赋值操作。
Enum Color{RED,GREEN,BLUE};
Enum Color light;
Scanf(“%d”,&light); 或者 light = 1;

十、动态内存分配

1.动态分配的空间在哪个区?有什么特点?

堆区,需要程序员自己申请,自己释放,如果不释放,程序结束后由操作系统释放。

2. 动态分配空间的函数有哪些?有什么区别?

Malloc calloc

函数调用形式:malloc(总的字节数) malloc 不会初始化申请的空间

Calloc(几块,每块几个字节)calloc 或初始化申请的空间

3.如何释放动态内存空间?

Free(p)

4. free 函数使用有什么注意事项?

free 必须释放的是堆区空间,不能释放栈区空间,比如局部变量,否则会造成程序崩溃

十一、宏定义

1.宏定义是来解决什么问题?在哪一个阶段进行处理?处理的规则是?

表达式(常量、变量、运算符和操作数)的复用,在于处理阶段完成替换,只会进行替换而不会 将后面的表达式看成一个整体。 比如
 #define M(x) x*x
Int a = 2,b=3;
M(a+b) == a+b*a+b = 2 + 2 *3 + 3 = 11

2.使用宏定义定义一个常量的值和使用const定义一个常量有什么区别?(#define N 100和const int n = 100

①处理阶段:宏定义在预处理阶段完成替换,const 常量在运行阶段分配空间

②占空间:宏定义不占空间, const 常量要占空间

3 、带参宏和函数的区别?

①处理阶段:带参宏在预处理阶段完成替换,函数在运行阶段执行

②占空间:宏定义不占空间,函数要占空间

③复杂逻辑:宏定义不能执行复杂逻辑,比如 if 嵌套,循环等,函数可以

十二、条件编译

1.什么是条件编译?

根据不同情况编译不同代码、产生不同目标文件的机制,称为条件编译。条件编译是预处理程 序的功能,不是编译器的功能。

2. 如何防止一个头文件的重复引用?

#ifndef __M__
#define __M__
#include<xx.h>
#endif

3. 条件结构和条件编译的不同?

①、选择结构是全部编译,条件编译时部分编译

②、选择结构是运行时处理,条件编译是预处理时处理。

相关文章
|
2月前
|
机器学习/深度学习 编译器 C语言
【C语言】数据输出的域宽控制(如何在输出数据时控制0占位)(如何输出前导0)(保留几位小数)(乘法口诀表打印不齐)等问题
【C语言】数据输出的域宽控制(如何在输出数据时控制0占位)(如何输出前导0)(保留几位小数)(乘法口诀表打印不齐)等问题
28 0
|
3月前
详解指针(超详细)(第二卷)
详解指针(超详细)(第二卷)
|
3月前
|
编译器
详解指针(超详细)(第三卷)
详解指针(超详细)(第三卷)
|
3月前
|
搜索推荐 算法 Serverless
详解指针(超详细)(第四卷)
详解指针(超详细)(第四卷)
|
10月前
|
存储
C进阶:指针(1)(下)
C进阶:指针(1)(下)
59 0
|
10月前
指针进阶(二)(下)
指针进阶(二)(下)
|
12月前
|
编译器 C语言 C++
C++入门(一)(上)
C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的程序,需要高度 的抽象和建模时,C语言则不合适。为了解决软件危机, 20世纪80年代, 计算机界提出了OOP(object oriented programming:面向对象)思想,支持面向对象的程序设计语言应运而生。
84 0
C++入门(一)(上)
|
12月前
|
自然语言处理 编译器 Linux
C++入门(一)(下)
缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该 形参的缺省值,否则使用指定的实参。
67 0
(开关问题)(枚举)(模拟)(位运算)116. 飞行员兄弟
(开关问题)(枚举)(模拟)(位运算)116. 飞行员兄弟
39 0
(枚举)(模拟)(前缀和)(数组模拟哈希)(可二分)1236. 递增三元组
(枚举)(模拟)(前缀和)(数组模拟哈希)(可二分)1236. 递增三元组
47 0