一、指针是C语言的灵魂

# include <stdio.h>

int main(){
int *p; //p是变量名,int *表示p变量存放的是int类型变量的地址,p是一个指针变量
int i = 3; //p = i; 这样写是错误的
//p = 4; 这样写是错误的
p = &i; //将i变量的地址给p变量
//p保存了i的地址,因此p指向i,修改p的值不影响i的值,修改i的值也不影响p的值 return 0;
}
# include <stdio.h>

int main(){
int *p; //不表示定义了一个名字叫做 *p的变量
//应该这样理解:p是变量名,p变量的数据类型是 int *类型
//int *类型实际就是存放int变量地址的类型 int i = 3; p = &i; printf("*P = %d\n", *p);
printf("i = %d\n", i);
return 0;
}

注释:1.如果p是个指针变量,并且p存放了普通变量i的地址,则p指向了普通变量
      2.*P 完全等同于 普通变量i  (有i出现的地方都可以替换成*p)

指针和指针变量的区别:

1.指针就是地址,地址就是指针,地址就是内存单元的编号,所以指针就是内存单元的编号

2.指针变量存放地址的变量,也就是说指针变量是存放内存单元编号的变量

3.指针和指针变量是两个不同的概念,但是要注意通常我们叙述时会把指针变量简称为指针,实际它们的含义不一样

二、指针的重要性:

1.表示一些复杂的数据结构

2.快速的传递数据

3.使函数返回一个以上的值(函数只能返回一个值)

4.能直接访问硬件

5.能够方便的处理字符串

6.是理解面向对象语言中引用的基础

# include <stdio.h>

int f(int a, int b);
void g(int * p ,int * q); int main(void){ int a = 100;
int b = 200; // a = f(a, b);
g(&a, &b);
printf("a = %d, b = %d\n", a, b); return 0;
}
//只能修改一个值
int f(int a, int b){ return 1;
}
//这样被调函数可以修改主调函数一个以上的值
void g(int * p ,int * q){
*p = 1;
*q = 2;
}

三、指针的定义

1、地址:内存单元的编号,地址是从零开始的非负整数。
2、范围:
     控制总线
CPU <---->    数据总线  <----->  内存条
     地址总线
控制线控制数据传输的方向 
数据线是传输数据
地址线是确定是控制哪个内存单元

cup<----->  数据总线 <-----> 内存条
一根线控制两个 0和1
两根线控制四个
n根线控制2的n次方个单元(字节)(每个单元是8位)

32位机 2x10^32
1G=2X10^30B(字节)
2x10^32 ~= 2X10^30*4  所以内存最大4G

3、指针:指针就是地址,地址就是指针,指针变量就是存放内存单元编号的变量。

指针本质就是一个操作受限(不能运算,只是编号)的非负整数(地址)

四、指针的分类

1、基本类型的指针

常见错误1:

# include <stdio.h>

int main(void){
int *p; //p指向一个垃圾值的地址,也就是一个垃圾地址
int i = 5; *p = i; // 就是将i的值给了一个不知道的地址,这样写不对
printf("%d\n", *p); return 0;
}

常见错误2:

# include <stdio.h>

int main(void){
int i = 5;
int *p;
int *q; p = &i
//*q = p; 语法编译出错
//*q = *p; error q指向一个垃圾地址
q = p; // error 可以读 q里面的垃圾地址,但是不能读*q的值,没有控制权限。
printf("%d\n", *q); return 0;
}

一个经典的指针程序:

# include <stdio.h>

void huhuan(int i, int j);
void zhizhenhuhuan(int * a, int * b);
void huhuan3(int * a, int * b); int main(void){
int a = 3;
int b = 5; // huhuan(a, b);
// zhizhenhuhuan(&a, &b);
huhuan3(&a, &b); printf("a = %d,b = %d\n", a, b); return 0;
} void huhuan(int a, int b){ //不能完成互换,a,b是形参,单独分配内存
int t; t = a;
a = b;
b = t;
} void zhizhenhuhuan(int * a, int * b){ //不能完成互换,互换了指针的指向
int * t; t = a;
a = b;
b = t;
} void huhuan3(int * a, int * b){ //可以完成互换,传递的是地址,交换的是地址指向的值
int t; t = *a;
*a = *b;
*b = t;
}

*的含义:

♥乘法   c = a*b;

♥定义指针变量 int * p;

♥取值运算符 *p

2、指针和数组的关系

一维数组名是个指针常量,它存放的是数组第一个元素地址

int a[5];
int b[5];
//a = b 是错误的 a,b都是常量
# include <stdio.h>

int main(void){
int a[5]; printf("%#x\n", &a[0]);
printf("%#x\n", a); return 0;
}

输出结果:0x12ff6c

0x12ff6c

如果p是个指针变量,则p[i]永远等价于 *(p+i)

确定一个一维数组需要两个参数:

数组第一个元素的地址

数组的长度

//f函数可以输出任何一个一维数组的内容
# include <stdio.h> void f(int * pArr, int len){
int i;
for (i=0; i<len; i++)
printf("%d ", *(pArr+i));
printf("\n");
}
int main(void){
int a[5] = {1, 2, 3, 4, 5};
int b[6] = {-1, -2, -3, 4, 5, -6};
int c[100] = {1, 99, 22, 33}; f(a, 5); //确定一个数组:数组首地址和长度
f(b, 6);
f(c, 100); return 0;
}
# include <stdio.h>

void f(int * pArr, int len){
pArr[3] = 88; //pArr[3]等价于a[3]也等价于*(a+3)和*(pArr+3)
// *a==a[0]
} int main(void){
int a[6] = {1, 2, 3, 4, 5, 6}; printf("%d\n", a[3]);
f(a, 6); // a和pArr都指向数组的第一个元素
printf("%d\n", *(a+3)); return 0;
}

五、指针变量的运算

指针变量不能相加,不能相乘,也不能相除(这些运算没有意义)

如果两个指针变量指向的是同一块连续空间中得不同的存储单元,则这两个指针才可以相减(这样减才有意义)

# include <stdio.h>

int main(void){
int i = 5;
int j = 10;
int * p = &i;
int * q = &j;
//此时p和q不能相减
int a[5];
p = &a[2];
q = &a[4]; printf("相减的结果为:%d\n", p-q);
//此时p和q可以相减,相减的值指p和q单元相隔的个数 return 0;
}

结果为:相减的结果为:-2

六、指针变量长度

预备知识:

sizeof(数据类型);或者 sizeof(变量名);返回该数据类型所占的字节数

例如: sizeof(int) = 4 sizeof(char) = 1

# include <stdio.h>

int main(void){
char ch = 'A';
int i = 90;
double x = 66.6;
char * p = &ch;
int *q = &i;
double *r = &x; printf("%d %d %d\n", sizeof(p), sizeof(q), sizeof(r));
}

输出的结果:4  4  4

七、多级指针

# include <stdio.h>

int main(void){
int i = 10;
int * p = &i;
int ** q = &p;
int *** r = &q; printf("i = %d\n", ***r); return 0;
}

结果: i = 10


忙里偷闲( ˇˍˇ )闲里偷学【C语言篇】——(5)有趣的指针的更多相关文章

  1. 忙里偷闲( ˇˍˇ )闲里偷学【C语言篇】——(2)准备知识

    一.变量为什么必须初始化? 在回答这个问题之前,我们先来运行一段代码: #include <stdio.h> int main(){ int i; printf("i=%d\n& ...

  2. 忙里偷闲( ˇˍˇ )闲里偷学【C语言篇】——(3)输入输出函数

    一.基本的输入和输出函数的用法 1.printf()  //屏幕输出 用法: (1)printf("字符串\n"); (2)printf("输出控制符", 输出 ...

  3. 忙里偷闲( ˇˍˇ )闲里偷学【C语言篇】——(1)GCC介绍及C语言编译过程

    一.GCC基本介绍 GCC(GNU Compiler Collection,GNU编译器套装),是一套由GNU开发的编程语言编译器.它是一套以GPL及LGPL许可证所发布的自由软件,也是GNU计划的关 ...

  4. 忙里偷闲( ˇˍˇ )闲里偷学【C语言篇】——(9)链表

    我们至少可以通过两种结构来存储数据 数组 1.需要一整块连续的存储空间,内存中可能没有 2.插入元素,删除元素效率极低. 3.查找数据快 链表 1.查找效率低 2.不需要一块连续的内存空间 3.插入删 ...

  5. 忙里偷闲( ˇˍˇ )闲里偷学【C语言篇】——(8)枚举、补码

    一.枚举 # include <stdio.h> enum WeekDay //定义了一个数据类型(值只能写以下值) { MonDay, TuesDay, WednesDay, Thurs ...

  6. 忙里偷闲( ˇˍˇ )闲里偷学【C语言篇】——(7)结构体

    一.为什么需要结构体? 为了表示一些复杂的事物,而普通类型无法满足实际需求 二.什么叫结构体? 把一些基本类型组合在一起形成的一个新的复合数据类型叫做结构体. 三.如何定义一个结构体? 第一种方式: ...

  7. 忙里偷闲( ˇˍˇ )闲里偷学【C语言篇】——(6)动态内存分配

    一.传统数组的缺点: 1.数组的长度必须事先定制,且只能是常整数,不能是变量 int len = 5; int a[len]; //error 2.传统形式定义的数组,该程序的内存程序员无法手动释放 ...

  8. 忙里偷闲( ˇˍˇ )闲里偷学【C语言篇】——(4)for == while ?

    一.for和while等价替换 int i = 1; for (i; i<=100; i++){ sum = sum + 1; } int i = 1; while(i<=100){ su ...

  9. 闲里偷忙的CPU-某个kwoker进程忙

    https://zhuanlan.zhihu.com/p/34311472 有一类比较特殊的CPU使用率问题,这类问题的特点是,系统平均CPU使用率很低,但是个别CPU的使用率非常高.今天借助这个真实 ...

随机推荐

  1. 【AIM Tech Round 4 (Div. 2) C】Sorting by Subsequences

    [链接]http://codeforces.com/contest/844/problem/C [题意] 水题,没有记录意义 [题解] 排序之后,记录每个数字原来在哪里就好. 可以形成环的. 环的个数 ...

  2. WPF 入门《常用控件》

    1.GroupBox 注意: GroupBox仍然需要布局容器来放置元素.如: StackPanel面板 <GroupBox Header="select number?"& ...

  3. 洛谷 P2692 覆盖

    P2692 覆盖 题目背景 WSR的学校有B个男生和G个女生都来到一个巨大的操场上扫地. 题目描述 操场可以看成是N 行M 列的方格矩阵,如下图(1)是一个4 行5 列的方格矩阵.每个男生负责打扫一些 ...

  4. [JWT] JWT Signature With RS256 - Learn The Advantages Compared to HS256

    The advantage of RS256 over HS256 is RS256 no longer need to share the secret key between client and ...

  5. domino web app

         近期在做个项目内容是:原企业的OA仅仅能在电脑桌面处理流程,不能在手机上处理审核功能,但随着企业需求,管理者需求在随时使用手机审核文档,达到及时处理文档及流程的及时性.      要求:1) ...

  6. (转)oracle 启动监听 报“监听程序不支持服务” 解决

    转自 http://www.51testing.com/html/99/478599-842622.html 今天安装了oracle后,启动监听,报错如下:    启动tnslsnr: 请稍候... ...

  7. Appium_Java运行测试脚本时问题汇总

    问题一.java.lang.NoClassDefFoundError: org/openqa/selenium/remote/SessionNotFoundExceptionCaused by: ja ...

  8. 原生js大总结九

    81.ES6的Symbol的作用是什么?   ES6引入了一种新的原始数据类型Symbol,表示独一无二的值   82.ES6中字符串和数组新增了那些方法   字符串       1.字符串模板    ...

  9. 洛谷——P1096 Hanoi双塔问题

    https://www.luogu.org/problem/show?pid=1096 题目描述 给定A.B.C三根足够长的细柱,在A柱上放有2n个中间有孔的圆盘,共有n个不同的尺寸,每个尺寸都有两个 ...

  10. 推荐一个iOS应用UI界面设计站点

    Patterns是一个分享ios应用UI界面的站点,专注于分享iOS应用UI界面的细节.依照设计元素进行分类,依照iOS经常使用功能对各类UI进行分类展示. 链接:url=http%3A%2F%2Fw ...