1.system

打开其他应用

1.指针演练  C 指针、

正如您所知道的,每一个变量都有一个内存位置,每一个内存位置都定义了可使用 & 运算符访问的地址,它表示了在内存中的一个地址。

#include <stdio.h>

int main ()
{
int var_runoob = 10;
int *p; // 定义指针变量
p = &var_runoob; printf("var_runoob 变量的地址: %p\n", p);
return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

var_runoob 变量的地址: 0x7ffeeaae08d8

什么是指针?

指针也就是内存地址,指针变量是用来存放内存地址的变量。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:

type*   var_name;
int    *ip;    /* 一个整型的指针 */
double *dp; /* 一个 double 型的指针 */
float *fp; /* 一个浮点型的指针 */
char *ch; /* 一个字符型的指针 */

如何使用指针?

使用指针时会频繁进行以下几个操作:定义一个指针变量、把变量地址赋值给指针、访问指针变量中可用地址的值。这些是通过使用一元运算符 * 来返回位于操作数所指定地址的变量的值。下面的实例涉及到了这些操作:

#include <stdio.h>

int main ()
{
int var = 20; /* 实际变量的声明 */
int *ip; /* 指针变量的声明 */ ip = &var; /* 在指针变量中存储 var 的地址 */ printf("var 变量的地址: %p\n", &var ); /* 在指针变量中存储的地址 */
printf("ip 变量存储的地址: %p\n", ip ); /* 使用指针访问值 */
printf("*ip 变量的值: %d\n", *ip ); return 0;
}
var 变量的地址: 0x7ffeeef168d8
ip 变量存储的地址: 0x7ffeeef168d8
*ip 变量的值: 20

C 中的 NULL 指针

在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为指针。

NULL 指针是一个定义在标准库中的值为零的常量。请看下面的程序:

#include <stdio.h>

int main ()
{
int *ptr = NULL; printf("ptr 的地址是 %p\n", ptr ); return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

ptr 的地址是 0x0

在大多数的操作系统上,程序不允许访问地址为 0 的内存,因为该内存是操作系统保留的。然而,内存地址 0 有特别重要的意义,它表明该指针不指向一个可访问的内存位置。但按照惯例,如果指针包含空值(零值),则假定它不指向任何东西。

如需检查一个空指针,您可以使用 if 语句,如下所示:

if(ptr) /* 如果 p 非空,则完成 */ if(!ptr) /* 如果 p 为空,则完成 */
 

C 指针详解

在 C 中,有很多指针相关的概念,这些概念都很简单,但是都很重要。下面列出了 C 程序员必须清楚的一些与指针相关的重要概念:

C 指针的算术运算

C 指针是一个用数值表示的地址。因此,您可以对指针执行算术运算。可以对指针进行四种算术运算:++、--、+、-。

假设 ptr 是一个指向地址 1000 的整型指针,是一个 32 位的整数,让我们对该指针执行下列的算术运算:

ptr++

在执行完上述的运算之后,ptr 将指向位置 1004,因为 ptr 每增加一次,它都将指向下一个整数位置,即当前位置往后移 4 字节。这个运算会在不影响内存位置中实际值的情况下,移动指针到下一个内存位置。如果 ptr 指向一个地址为 1000 的字符,上面的运算会导致指针指向位置 1001,因为下一个字符位置是在 1001。

我们概括一下:

  • 指针的每一次递增,它其实会指向下一个元素的存储单元。
  • 指针的每一次递减,它都会指向前一个元素的存储单元。
  • 指针在递增和递减时跳跃的字节数取决于指针所指向变量数据类型长度,比如 int 就是 4 个字节。

递增一个指针

我们喜欢在程序中使用指针代替数组,因为变量指针可以递增,而数组不能递增,数组可以看成一个指针常量。下面的程序递增变量指针,以便顺序访问数组中的每一个元素:

#include <stdio.h>

const int MAX = 3;

int main ()
{
int var[] = {10, 100, 200};
int i, *ptr; /* 指针中的数组地址 */
ptr = var;
for ( i = 0; i < MAX; i++)
{ printf("存储地址:var[%d] = %p\n", i, ptr );
printf("存储值:var[%d] = %d\n", i, *ptr ); /* 指向下一个位置 */
ptr++;
}
return 0;
}

函数指针

函数指针是指向函数的指针变量。

通常我们说的指针变量是指向一个整型、字符型或数组等变量,而函数指针是指向函数。

函数指针可以像一般函数一样,用于调用函数、传递参数。

函数指针变量的声明:

typedef int (*fun_ptr)(int,int); // 声明一个指向同样参数、返回值的函数指针类型
#include <stdio.h>

int max(int x, int y)
{
return x > y ? x : y;
} int main(void)
{
/* p 是函数指针 */
int (* p)(int, int) = & max; // &可以省略
int a, b, c, d; printf("请输入三个数字:");
scanf("%d %d %d", & a, & b, & c); /* 与直接调用函数等价,d = max(max(a, b), c) */
d = p(p(a, b), c); printf("最大的数字是: %d\n", d); return 0;
}

回调函数

函数指针作为某个函数的参数

函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的函数。

简单讲:回调函数是由别人的函数执行时调用你实现的函数。

以下是来自知乎作者常溪玲的解说:

你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。

实例

实例中 populate_array() 函数定义了三个参数,其中第三个参数是函数的指针,通过该函数来设置数组的值。

实例中我们定义了回调函数 getNextRandomValue(),它返回一个随机值,它作为一个函数指针传递给 populate_array() 函数。

populate_array() 将调用 10 次回调函数,并将回调函数的返回值赋值给数组。

#include <stdlib.h>
#include <stdio.h> void populate_array(int *array, size_t arraySize, int (*getNextValue)(void))
{
for (size_t i=0; i<arraySize; i++)
array[i] = getNextValue();
} // 获取随机值
int getNextRandomValue(void)
{
return rand();
} int main(void)
{
int myarray[10];
/* getNextRandomValue 不能加括号,否则无法编译,因为加上括号之后相当于传入此参数时传入了 int , 而不是函数指针*/
populate_array(myarray, 10, getNextRandomValue);
for(int i = 0; i < 10; i++) {
printf("%d ", myarray[i]);
}
printf("\n");
return 0;
}

C语言知识补充 --来自菜鸟教程的指针复习的更多相关文章

  1. Http状态码大全(来自菜鸟教程)

    HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准. HTTP是一个基于TCP/IP通信 ...

  2. C语言经典例题(菜鸟教程100例)

    学习c语言基础,怎么能少了菜鸟教程上的100道例题呢,这里整理一下每道题的链接,希望大家能享受学习的乐趣 1,有1,2,3,4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 2,企业发放 ...

  3. 菜鸟教程 Python100例 之实例29

    学习编程的路,走得好艰辛... 为了巩固基础知识,把菜鸟教程网上的实例拿来练习.. 在做到实例29时,看了网站给出的代码,觉得可以加强一下功能,不由得动了一下脑筋,如下: 原文题目: 题目:给一个不多 ...

  4. 曹工说Redis源码(2)-- redis server 启动过程解析及简单c语言基础知识补充

    文章导航 Redis源码系列的初衷,是帮助我们更好地理解Redis,更懂Redis,而怎么才能懂,光看是不够的,建议跟着下面的这一篇,把环境搭建起来,后续可以自己阅读源码,或者跟着我这边一起阅读.由于 ...

  5. 用汇编语言(ARM 32位)编写TCP Bind Shell的菜鸟教程

    用汇编语言(ARM 32位)编写TCP Bind Shell的菜鸟教程 来源 https://www.4hou.com/info/news/9959.html Change 新闻 2018年1月19日 ...

  6. 学习笔记之C# 教程 | 菜鸟教程

    C# 教程 | 菜鸟教程 http://www.runoob.com/csharp/csharp-tutorial.html 菜鸟教程在线编辑器 http://www.runoob.com/try/r ...

  7. 关于C语言知识调查

    因为上一篇随笔对这一部分写得不够清楚,因此在这篇做一些补充. 你是怎么学习C语言的? 起初,对于C语言的学习主要是通过老师课堂的教学,完成相关的课后作业.与我的技能相比的话,他们都有一个共同点需要去实 ...

  8. 菜鸟教程之学习Shell script笔记(下)

    菜鸟教程Shell script学习笔记(下) 以下内容是学习菜鸟教程之shell教程,所整理的笔记 菜鸟教程之shell教程:http://www.runoob.com/linux/linux-sh ...

  9. 菜鸟教程之学习Shell script笔记(上)

    菜鸟教程之学习Shell script笔记 以下内容是,学习菜鸟shell教程整理的笔记 菜鸟教程之shell教程:http://www.runoob.com/linux/linux-shell.ht ...

  10. Android知识补充(Android学习笔记)

    Android知识补充 ●国际化 所谓的国际化,就是指软件在开发时就应该具备支持多种语言和地区的功能,也就是说开发的软件能同时应对不同国家和地区的用户访问,并针对不同国家和地区的用户,提供相应的.符合 ...

随机推荐

  1. 北极星Polaris+Gateway动态网关配置!

    springcloudtencetn 父工程: pom <?xml version="1.0" encoding="UTF-8"?> <pro ...

  2. 爬虫之xpath插件下载与安装

    目录 简介: 下载xpath文件 打开chrome浏览器 点击右上角小圆点 更多工具.阔展程序 拖拽xpath插件放到阔展程序 如果失效,再次拖拽 关闭浏览器重新打开 按ctrl+shift+x 出现 ...

  3. Promise知一二

    Promise 1.Promise的前置知识 进程(厂房) 程序的运行环境 线程(工人) 线程是实际进行运算的东西 同步 通常情况代码都是自上向下一行一行执行的 前边的代码不执行后边的代码也不会执行 ...

  4. 【Shell案例】【小数点scale&bc】14、求平均值

    描述写一个bash脚本以实现一个需求,求输入的一个的数组的平均值 第1行为输入的数组长度N第2~N行为数组的元素,如以下为:数组长度为4,数组元素为1 2 9 8示例:41298 那么平均值为:5.0 ...

  5. python面向对象推导流程

    举例:猫狗大战 # 1.例如我们要编写一个猫狗对战小游戏 # 首先我们要定义一个猫,和一只狗 cat1 = { 'name': '小白猫', 'type': '宠物猫', 'attack_val': ...

  6. 日爬百万数据的域名限制、url的清洗和管理

    一.域名去重1.检测开头:link.startswith('http') txt = "Hello, welcome to my world." x = txt.startswit ...

  7. new的函数如果有return

    1 function FnA() { return { a: 1 } } 2 function FnB() { return false } 3 function FnC() { return tru ...

  8. 新款 c++ web framework 支持orm http/2

    c++ web framework很少, 随着c++ 热度升温,c++ 在人工智能 自然语言处理 加快应用. 最近一款国产 c++ web framework 问世 写业务速度跟脚步语言一样速度 自带 ...

  9. 普冉PY32系列(二) Ubuntu GCC Toolchain和VSCode开发环境

    目录 普冉PY32系列(一) PY32F0系列32位Cortex M0+ MCU简介 普冉PY32系列(二) Ubuntu GCC Toolchain和VSCode开发环境 以下介绍PY32F0系列在 ...

  10. 算法之SPFA的前置:Bellman-Ford算法

    SPFA 我们都知道一个叫SPFA的算法,它是用来计算单源最短路径的,但是,众所周知它不是很稳定,容易退化. SPFA是基于什么被提出的? 基于一个叫做Bellman-Ford的算法. Bellman ...