第4章 指针和数组

1. int *p=NULL 和 *p=NULL 有什么区别

int *p = NULL;

  第一句代码的意思是:定义一个指针变量p,其指向的内存里面保存的是 int类型的数据;在定义变量的同时把p的值设置为 0x00000000,而不是把 *p的值设置为 0x00000000,这个过程称为初始化,是在编译的时候进行的。

int *p;
*p = NULL;

  第一行代码,定义了一个指针变量p,其指向的内存里面保存的是 int类型的数据,但是这时候p本身的是多少不得而知;第二行代码,给 *p赋值为NULL。

2.如何往内存地址 0x12ff7c 上存入一个整形数 0x100?

  •   第一种方法
  • int *p = (int *)0x12ff7c; //p
    *p = 0x100;
  •   第二种方法
  • *(int *)0x12ff7c = 0x100;

3.数组的内存布局

int a[] ;

  a作为右值时,代表数组首元素的首地址,而非数组的首地址。

  a[0],a[1]等为a的元素,但并非元素的名字,数组的每一个元素都是没有名字的。

  sizeof(a[5])的值在32为系统下为4,为什么没有出错?

其实函数求值是在运行的时候,而sizeof求值是在编译的时候。虽然并不存在a[5]这个元素,但是这里也并没有真正访问a[5],而是仅仅根据数组元素的类型来确定其值。所以没有出错。

4.&a[0]和&a的区别

  前者是数组首元素的首地址,而后者是数组的首地址。

5.数组名a作为左值和右值的区别

x = y;

  左值:在这个上下文环境中,编译器认为x的含义是x所代表的地址。这个地址只有编译器知道,在编译的时候确定

  右值:在这个上下文环境中。编译器认为y的含义是y所代表的地址里面的内容。这个内容运行的时候确定。

  a作为右值时其意义与 &a[0] 是一样的,代表的是数组首元素的首地址,而不是数组的首地址。

  a不能作为左值!编译器认为数组名作为左值代表的意思是a的首元素的首地址,但是这个地址开始的一块内存是一个总体,我们只能访问数组的某个元素,而无法把数组当成一个总体来进行访问。

6.以指针的形式访问指针和以下标的形式访问指针

char *p = "abcdef";
  • 以指针的形式:*(p+4)。先取出p里面的地址值,假设为0x0000ff00,再加上4个字符的偏移量,得到新的地址0x0000ff04;然后再取出地址上的值。
  • 以下标的形式:p[4]。编译器总是把下标的形式的操作解析为以指针的形式的操作。先取出p里存储的地址值;再加上4个元素的偏移量,计算出新的地址;然后再从新的地址中取出值。

7.以指针的形式访问数组和以下标的形式访问数组

  对a的元素的访问必须先根据数组的名字a找到数组首元素的首地址,然后再根据偏移量找到相应的值。这是一种典型的“具名 + 匿名”的访问。

8.指针数组和数组指针

  指针数组:储存指针的数组

  数组指针:指向数组的指针

int *p1[]; //指针数组

  p1先与“[]”结合,构成一个数组的定义,数组名为p1,int *修饰的是数组里的每个元素。也就是说,这是一个数组,其包含10个指向int类型数据的指针,即指针数组

int (*p2)[]; //数组指针

  “*”和p2构成一个指针的定义,指针变量名为p2,int修饰的是数组的内容。数组在这里没有名字,是个匿名数组。也就是说,p2是一个指针,它指向一个包含10个int类型数据的数组,即数组指针。

9.再论a和&a之间的区别

 int main()
{
char a[] = {'A','B','C','D'};
char (* p3)[] = &a;
char (* p4)[] = a;
return ;
}

  编译器会给出警告。因为p4这个定义“=”两边的的数据类型不一致。左边的数据类型是指向整个数组的指针,右边的数据类型是指向单个字符的指针。

10.地址的强制转换

struct Test
{
int Num;
char *pcName;
short sDate;
char cha[];
short sBa[];
}*p;

  假设p的值为0x100000,那么

  p + 0x1 = 0x100014

  (unsigned long)p + 0x1 =0x100001

  (unsigned int *)p + 0x1 = 0x100004

  第一个表达式p + 0x1的值为 0x100000+sizeof(Test)*0x1。Test的大小为20字节

  第二个表达式其实就是一个无符号的长整数加上另一个整数

  第三个表达式的p被强制转换为指向无符号整型的指针

11.数组参数和指针参数

  C语言中,当一维数组作为函数参数的时候,编译器总是把它解析成一个指向其首元素首地址的指针。

  函数的返回值也不能是一个数组,而只能是指针。

void fun(char *p)
{
char c = p[];
}
void fun(char a[])
{
char c = a[];
}

两组代码等效,但第二个形式较好。

  main函数内的变量不是全局变量,而是局部变量,只不过它的生命周期和全局变量一样长而已。全局变量一定是定义在函数外部的。

11.二维数组参数和二级指针参数

  C语言中,当一维数组作为函数参数的时候,编译器总是把它解析成一个指向其首元素首地址的指针。所以下面两个函数声明是一样的:

  void fun(char a[3][4]),void fun(char a[][4]) 和 void fun(char (*p)[4])

  void fun(char *p[4])和void fun(char **p)  这是因为*p[4]是一个包含4个指针的一位数组,把这个一位数组也写成指针的形式,就得到第二种写法。

12.函数指针

  函数指针就是函数的指针,它是一个指针,指向一个函数。

char * fun1(char * p1,char * p2);

fun1是函数名,p1,p2是参数,其类型为char *类型,函数的返回值是char *

char * * fun2(char * p1,char * p2);

与上例唯一不同的是,函数返回值类型为 char **

char * (* fun3)(char * p1,char * p2);

fun3是一个指针变量,它指向一个函数。这个函数有两个指针类型的参数,函数的返回值也是一个指针。

13.函数指针的例子

 #include<stdio.h>
char * fun(char * p1,char * p2)
{
}
int main()
{
char * (* pf)(char * p1,char * p2);
pf = &fun;
(* pf)("aa","bb");
return ;
}

  给函数指针赋值时,可以用&fun或字节使用函数名fun。

14. *(int *)&p

 void fun()
{
}
int main()
{
void (* p)();
*(int *)&p = (int)fun;
(*p)();
return ;
}

  void (* p)();这行代码定义了一个指针变量p,p指向一个函数,这个函数的参数和返回值都是void。

 &p求指针变量p本身的地址。
 (int)fun表示将函数的入口地址转换成指向int类型的指针
  *(int *)&p = (int)fun;表示将函数的入口地址赋值给指针变量p
 (*p)()就是对函数的调用。
15.(*(void(*)())0)()
void(*)(),这是一个函数指针类型
(void(*)())0,将0强制转换为函数指针类型。
(*(void(*)())0),取0地址开始的一段内存内存里面的内容,其内容就是保存在首地址为0的一段区域内的函数
(*(void(*)())0)(),函数的调用
16.函数指针数组
char * (*pf[])(char *p);

  这里定义了一个函数指针数组。它是一个数组,数组名为pf,数组内存储了3个指向函数的指针,这些指针指向一些返回值类型为指向字符的指针,参数为一个指向字符的指针的函数。

17.函数指针数组指针

char * (*(*pf)[])(char * p)

  这里的函数指针数组指针不就是一个指针嘛。只不过这个指针指向一个数组,这个数组里面存的是指向函数的指针。

 
 
 
												

《C语言深度解剖》学习笔记之指针和数组的更多相关文章

  1. C语言深度解剖读书笔记

    开始本节学习笔记之前,先说几句题外话.其实对于C语言深度解剖这本书来说,看完了有一段时间了,一直没有时间来写这篇博客.正巧还刚刚看完了国嵌唐老师的C语言视频,觉得两者是异曲同工,所以就把两者一起记录下 ...

  2. C语言深度解剖读书笔记(6.函数的核心)

    对于本节的函数内容其实就没什么难点了,但是对于函数这节又涉及到了顺序点的问题,我觉得可以还是忽略吧. 本节知识点: 1.函数中的顺序点:f(k,k++);  这样的问题大多跟编译器有关,不要去刻意追求 ...

  3. 【转】 C语言深度解剖读书笔记(1.关键字的秘密)

    本文出处:http://blog.csdn.net/mbh_1991/article/details/10149805 开始本节学习笔记之前,先说几句题外话.其实对于C语言深度解剖这本书来说,看完了有 ...

  4. c语言深度解剖(笔记)

    1.1最宽恒大量的关键字----auto 函数内部变量,限制作用域为这个 1.2.1最快的关键字---- register函数. 关键字请求编译器尽可能的将变量存在 CPU 内部寄存器中 1.2.2使 ...

  5. R语言与机器学习学习笔记

    人工神经网络(ANN),简称神经网络,是一种模仿生物神经网络的结构和功能的数学模型或计算模型.神经网络由大量的人工神经元联结进行计算.大多数情况下人工神经网络能在外界信息的基础上改变内部结构,是一种自 ...

  6. go语言,golang学习笔记4 用beego跑一个web应用

    go语言,golang学习笔记4 用beego跑一个web应用 首页 - beego: 简约 & 强大并存的 Go 应用框架https://beego.me/ 更新的命令是加个 -u 参数,g ...

  7. go语言,golang学习笔记3 用命令下载框架报错问题解决 设置环境变量

    go语言,golang学习笔记3 用命令下载框架报错问题解决 设置环境变量 下载安装:go get github.com/astaxie/beego 首页 - beego: 简约 & 强大并存 ...

  8. go语言,golang学习笔记2 web框架选择

    go语言,golang学习笔记2 web框架选择 用什么go web框架比较好呢?能不能推荐个中文资料多的web框架呢? beego框架用的人最多,中文资料最多 首页 - beego: 简约 & ...

  9. go语言,golang学习笔记1 官网下载安装,中文社区,开发工具LiteIDE

    go语言,golang学习笔记1 官网下载安装,中文社区,开发工具LiteIDE Go语言是谷歌2009发布的专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速 ...

随机推荐

  1. MongoDB命令的简单操作(一)

    MongoDB是工作在集合和文档上的一种概念. 1.创建数据库 use name2.查看所以的数据库列表 show dbs3.查看当前数据库 db4.向数据库插入数据 db.items.insert( ...

  2. ActiveMQ消息中间件

    最近学习到ActiveMQ,之前也没有用过相关或者类似的工具,因此特地写个文章进行相关的学习记录. 相关参考博文:https://www.cnblogs.com/cyfonly/p/6380860.h ...

  3. 通过inputSplit分片size控制map数目

    前言:在具体执行Hadoop程序的时候,我们要根据不同的情况来设置Map的个数.除了设置固定的每个节点上可运行的最大map个数外,我们还需要控制真正执行Map操作的任务个数. 1.如何控制实际运行的m ...

  4. SQLyog12.0.9下载、安装和破解

    原文转载连接:https://blog.csdn.net/lihua5419/article/details/73881837/ sqlyog百度云链接(永久有效):http://pan.baidu. ...

  5. DIV+CSS网页布局常用的一些基础知识整理

    CSS命名规范 一.文件命名规范 全局样式:global.css: 框架布局:layout.css: 字体样式:font.css: 链接样式:link.css: 打印样式:print.css: 二.常 ...

  6. PYTHON网络爬虫与信息提取[scrapy框架应用](单元十、十一)

    scrapy 常用命令 startproject  创建一个新的工程 scrapy startproject <name>[dir] genspider    创建一个爬虫         ...

  7. date、cal和clear命令

    一.date命令 date命令的功能:date命令是显示或设置系统时间与日期. 很多shell脚本里面需要打印不同格式的时间或日期,以及要根据时间和日期执行操作.延时通常用于脚本执行过程中提供一段等待 ...

  8. 【JZOJ4763】【NOIP2016提高A组模拟9.7】旷野大计算

    题目描述 输入 输出 样例输入 5 5 9 8 7 8 9 1 2 3 4 4 4 1 4 2 4 样例输出 9 8 8 16 16 数据范围 解法 离线莫队做法 考虑使用莫队,但由于在删数的时候难以 ...

  9. 手机monkey测试BUG重现及解决方法

    目录 1.1 Monkey测试简介...1 1.2 Monkey程序介绍...1 1.3 Monkey命令的简单帮助...2 1.4 Monkey命令参数介绍...2 1.5 Monkey测试步骤.. ...

  10. RNN与 LSTM 网络

    循环神经网络(RNN) 人们的每次思考并不都是从零开始的.比如说你在阅读这篇文章时,你基于对前面的文字的理解来理解你目前阅读到的文字,而不是每读到一个文字时,都抛弃掉前面的思考,从头开始.你的记忆是有 ...