=============================================================================

指针变量之间赋值是需要兼容的。

例如:
int *a = int的地址
char *b= char的地址
--------------------------------------
void类型的指针可以做任意类型地址的赋值操作。
例如:
void *p = int地址可以
p = char地址也还可以

但void类型的指针不能做指针运算。
例如:
p++; //会出现问题
--------------------------------------
指针与数组的关系
int a[10];
int *p = a;   //初始化的时候就指向了首地址,相当于int *p = &a[0]; 也相当于int *p; p = a; 也相当于int *p; p = &a[0];
p[3] = 8;    //等价于*(p + 3) = 8;该p[3]对应的是下标为3的元素。

p += 2;      //指针进行运算后
p[3] = 0;   //此时的p[3]对应的元素为下标为5的元素。

a += 2;     //这样写是错误的,因为数组名是一个地址的编号,是一个常量(该常量的解释是:变化的常量。因为每一次运行程序时,地址编号都会发生变化,所以是变化的;又因为一旦程序运行了,那么地址的编号就随之确定了,不能改变了,所以就是常量了!)

p = a + 2;   //因为int *p; p = a; 所以p += 2; --> p = p + 2; --> p = a + 2;  //又因为a是一个地址编号,是一个常量,可以做右值的。
--------------------------------------
指针的运算:指针的加减不是普通整数的加减

例如:
int ab[10];
short *p = ab;    //一个short类型的指针变量,指向了一个int型的地址,但不影响p本身的类型。
p += 2;      //p在内存中移动了4个字节, 结果是移动到了ab[1]的地址了。
int *p1 = ab;
p1 += 2;        //p在内存中移动了8个字节,移动到了ab[2]的地址了。

short abc[10];
p1 = abc;
p1 += 3;       //这时p1移动了12个字节。

指针运算的时候,不要在意指针具体指向一个什么样类型的地址,要在意的是指针本身是什么样的类型。
--------------------------------------
指针数组:main函数的参数就是一个典型的指针数组(也即二级指针)。

int *a[10];    //定义了一个数组,名字叫a,有10个成员,每个成员的类型是int *,成员分别为a[0]、a[1]、......、a[9]。
char *b[10];      //定义了一个数组,名字叫b,有10个成员,每个成员的类型是char *,成员分别为b[0]、b[1]、......、b[9]。
sizeof(a) = 8 个字节, sizeof(b) = 8 个字节。
--------------------------------------
该定义一个什么类型的指针才能指向指针数组b(char *b[10];)呢?
答:
char **p = b;
p[0]是char *类型。此时p[0] = b[0]; p[1] = b[1]; ...... p[9] = b[9];

若如下这样定义的话,就不兼容:
char *p = b;
此时的p[0]是char类型。
但b[0]本身是什么类型呢?答:b[0]是char *类型。此时 p[0] 不等于 b[0]了。
--------------------------------------
该定义一个什么类型的指针才能指向数组b(char b[10];)呢?
答:
char *p = b;
此时的p[0]是char类型,此时p[0] = b[0]; p[1] = b[1]; ...... p[9] = b[9];
--------------------------------------
指向指针的指针(二级指针)

int *p;
*p是什么类型?答:int类型。

int ***p
*p是什么类型?答:int **类型。
**p是int *类型。
***p是int类型。
--------------------------------------
指针变量作为函数参数
如果想要通过函数内部修改外部是实参的值,就需要给函数的参数传递实参的地址。
--------------------------------------
一维数组名作为函数参数

一维数组名一旦作为函数参数,c语言将数组名解释为一级指针变量。(由数组名(常量)变为指针变量名(变量))
int abc(int a[10])
int abc(int a[])
int abc(int *a)

如果将一个数组作为函数的形参进行传递,那么数组内容可以在被调用的函数内部进行修改,
很多时候,我们不希望这样的事情发生,所以用到const对形参进行修饰。(尽管此种修饰方法没有用!)
int abc(const int a[10])
--------------------------------------
指针 和 字符串
在c语言中,大多数的字符串(字符数组)操作其实就是指针操作。

例如:

 #include <stdio.h>

 int main()
{
char s[] = "hello world";
char *p = s;
p[] = 'a';
*p = 'b'; printf("%s\n", s); //bello world char *c = "hello world";
//c[0] = 'a';//编译没有问题,但运行会出现段错误。因为c指向的是一个常量。 printf("%d\n", *c); //
printf("%d\n", c[]); //
printf("%d\n", c[]); // return ;
}

--------------------------------------
char a[100] = "hello world";   //定义一个数组,有100个char,同时初始化数组成员变量的值。
char *p = a;            //定义一个char *类型的指针p,p指向char类型数组的首元素地址。
char *s = "hello world";       //定义了一个字符串常量,s指向这个常量的首地址。
const char *s = "hello world";  //定义了一个字符串常量,s指向这个常量的首地址。(更严谨的写法)

a[0] = 'a'; //合法的,因为数组a的所有成员都是变量。
s[0] = 'a'; //非法的,因为s指向的是一个常量。
--------------------------------------
char *作为函数的参数

此时函数的参数是字符串。
--------------------------------------
如果函数的参数是一个数组,那么函数内部是不知道这个数组成员数量的,所以函数的形参需要额外再增加一个参数,说明数组成员数量。
如果函数的参数是一个字符串(本质是字符数组),那么就不需要增加额外参数说明字符串字符数量了。
--------------------------------------
指针数组作为main函数的参数(即形参)

int main(int a, char *b[10]
int main(int a, char *b[])
int main(int a, char **b)
int main(int argc, char **args)

main函数的第一个参数是标示第二个参数有几个成员,不要尝试修改main函数的参数的顺序。
=============================================================================

c语言基础学习07_关于指针的复习的更多相关文章

  1. Golang 汇编asm语言基础学习

    Golang 汇编asm语言基础学习 一.CPU 基础知识 cpu 内部结构 cpu 内部主要是由寄存器.控制器.运算器和时钟四个部分组成. 寄存器:用来暂时存放指令.数据等对象.它是一个更快的内存. ...

  2. D02-R语言基础学习

    R语言基础学习——D02 20190423内容纲要: 1.前言 2.向量操作 (1)常规操作 (2)不定长向量计算 (3)序列 (4)向量的删除与保留 3.列表详解 (1)列表的索引 (2)列表得元素 ...

  3. D01-R语言基础学习

    R语言基础学习——D01 20190410内容纲要: 1.R的下载与安装 2.R包的安装与使用方法 (1)查看已安装的包 (2)查看是否安装过包 (3)安装包 (4)更新包 3.结果的重用 4.R处理 ...

  4. D03——C语言基础学习PYTHON

    C语言基础学习PYTHON——基础学习D03 20180804内容纲要: 1 函数的基本概念 2 函数的参数 3 函数的全局变量与局部变量 4 函数的返回值 5 递归函数 6 高阶函数 7 匿名函数 ...

  5. D03-R语言基础学习

    R语言基础学习——D03 20190423内容纲要: 1.导入数据 (1)从键盘输入 (2)从文本文件导入 (3)从excel文件导入 2.用户自定义函数   3.R访问MySQL数据库 (1)安装R ...

  6. go语言基础学习

    go基础学习,面向对象-方法在Go语言中,可以给任意自定义类型(包括内置类型,但不包括指针类型)添加相应的方法 使用= 和:=的区别: // = 使用必须使用先var声明例如: var a a=100 ...

  7. C# 语言基础学习路线图

    一直以来,对于很多知识点都是存于收藏夹中,随着时间地变更,收藏夹中链接也起来越多,从未进行整理,也很零散,所以想对曾经遇到并使用过的一些知识形成文档,作为个人知识库的一部分. 就从C# 语言基础开始, ...

  8. 计算机专业C语言编程学习重点:指针化难为易

    C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...

  9. C语言基础学习

    汇编语言又叫符号语言 出来机器语言和汇编语言外其他语言必须经过翻译(编译,和解释行)才可以执行 .c --> 编译(翻译成二进制代码 .obj) 链接 把目标程序和库函数以及其他目标程序链接起来 ...

随机推荐

  1. Jmeter3.2版本中Generating Report Dashboard功能浅析

    自从投入到Jmeter怀抱,一直想找到一个比较不错的测试结果报告模板用于展示,类似于Loadrunner中导出html那种,但是苦苦的寻找始终没有一款让我看上眼的,包括Jmeter自带的xsl,虽然展 ...

  2. JavaBean转Map方法

    Map<String, Object> fieldMap =new HashMap<String, Object>(); BeanInfo beanInfo = Introsp ...

  3. swig官方go Examples 源码勘误

    勘误 在官网下载页面(http://www.swig.org/download.html )下载的swigwin-3.0.12包中go示例源码有个错误(swigwin-3.0.12\Examples\ ...

  4. 深入理解 React JS 中的 setState

    此文主要探讨了 React JS 中的 setState 背后的机制,供深入学习 React 研究之用. 在课程 React.js入门基础与案例开发 中,有些同学会发现 React JS 中的 set ...

  5. android inline hook

    最近终于沉下心来对着书把hook跟注入方面的代码敲了一遍,打算写几个博客把它们记录下来. 第一次介绍一下我感觉难度最大的inline hook,实现代码参考了腾讯GAD的游戏安全入门. inline ...

  6. Android Studio移动鼠标显示悬浮提示的设置方法

    欢迎和大家交流技术相关问题: 邮箱: jiangxinnju@163.com 博客园地址: http://www.cnblogs.com/jiangxinnju GitHub地址: https://g ...

  7. 在Ubuntu下安装OpenJDK的方法

    最近在看<深入理解Java虚拟机>就想试一下在ubuntu下安装一个自己的虚拟机,说实话还是废了些功夫的. 首先我的ubuntu版本是Ubuntu 14.04.5, 于是我就去OpenJD ...

  8. 嵌入式linux下wifi网卡的使用(二)——应用程序iw编译

    首先编译iw,Iw支持两种加密/认证方式.第一种是OPEN/OPEN 第二种是WEP/WEP在网上下载iw源码,发现iw的编译需要依赖libnl库(这个库是为了方便应用程序使用netlink借口而开发 ...

  9. [Spark内核] 第30课:Master的注册机制和状态管理解密

    本課主題 Master 接收 Worker, Driver, Application Master 处理 Driver 狀态变换 Master 处理 Executor 狀态变换 [引言部份:你希望读者 ...

  10. js上传图片

    额    呆坐许久  感觉 有很多想写的  就是不知从何写起..贼尴尬. 其实 我平时项目中 基本上传图片什么的  都是跟着from 表单 一起提交给后台的 实行起来 简单暴力 连图片预览的都没有写 ...