指针变量用来记录地址数据,指针变量的用途就是找到另外一个变量,没有记录有效地址的指针不能用来找到其它变量,声明指针变量时必须在变量名称前写*.如果一个指针变量记录了另外一个变量的地址就可以认为它们之间存在捆绑关系,在指针变量名称前使用*操作符可以表示它所捆绑的变量

/*
* 指针演示
* */
#include <stdio.h>
int main() {
int num = 0, num1 = 0, num2 = 0, tmp = 0;
int *p_num = &num, *p_num1 = &num1, *p_num2 = &num2, *p_tmp = &tmp;
printf("请输入三个数字:");
scanf("%d%d%d", p_num, p_num1, p_num2);
/*if (*p_num > *p_num1) {
*p_tmp = *p_num;
*p_num = *p_num1;
*p_num1 = *p_tmp;
}
if (*p_num > *p_num2) {
*p_tmp = *p_num;
*p_num = *p_num2;
*p_num2 = *p_tmp;
}
if (*p_num1 > *p_num2) {
*p_tmp = *p_num1;
*p_num1 = *p_num2;
*p_num2 = *p_tmp;
}*/
if (*p_num > *p_num1) {
p_tmp = p_num;
p_num = p_num1;
p_num1 = p_tmp;
}
if (*p_num > *p_num2) {
p_tmp = p_num;
p_num = p_num2;
p_num2 = p_tmp;
}
if (*p_num1 > *p_num2) {
p_tmp = p_num1;
p_num1 = p_num2;
p_num2 = p_tmp;
}
printf("%d %d %d\n", *p_num, *p_num1, *p_num2);
return 0;
}

声明指针变量的时候也需要提供类型名称,它表示这个指针适合与什么类型的存储区捆绑

可以在一条语句里声明多个同类型指针,必须在每个指针变量名称前单独加*

没有记录有效地址的指针分为两类
  1.空指针里面记录空地址(NULL),这个地址的数值就是0.
  2.其他没有记录有效地址的指针都叫做野指针

程序里禁止出现野指针,所有指针变量必须初始化

/*
* 指针演示
* */
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5}, num = 0;
int *p_num = arr;
for (num = 0;num <= 4;num++) {
printf("%d ", arr[num]);
printf("%d ", p_num[num]);
}
printf("\n");
return 0;
}

对指针变量进行初始化的时候*没有参与赋值过程,指针和变量的捆绑关系会随着程序的执行不断变化,指针可以看作是存储区的某种身份

如果指针和数组里第一个存储区捆绑就可以通过指针找到数组里的每个存储区,指针后使用下标就可以表示数组里的存储区

地址数据可以参与如下计算过程
地址 + 整数 地址 - 整数 地址 - 地址
地址加减整数n实际上加减的是n个捆绑存储区的大小.数组名称加下标可以得到下标对应存储区的地址,采用如下写法也可以表示数组里的存储区
*(arr + num)
其中arr是数组名称,num是下标,这个写法可以表示数组里下标为num的存储区,地址减地址的结果是两个地址之间包含的捆绑存储区个数

/*
* 地址计算规则演示
* */
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
int *p_num = arr;
printf("arr是%p,arr + 3是%p, arr - 3是%p\n", arr, arr + 3, arr - 3);
printf("&arr[3]是%p\n", &arr[3]);
printf("arr[3]是%d\n", arr[3]);
printf("*(arr + 3)是%d\n", *(arr + 3));
printf("p_num[3]是%d\n", p_num[3]);
printf("*(p_num + 3)是%d\n", *(p_num + 3));
printf("&arr[3] - arr是%d\n", &arr[3] - arr);
return 0;
}

可以使用const关键字声明指针变量,声明指针变量的时候可以把const关键字写在指针变量名称前。这种指针不可以被赋值,但是可以通过这种指针对它的捆绑存储区进行赋值。

声明指针变量的时候可以把const关键字写在类型名称前面。这种指针本身可以被赋值,但是不可以通过这种指针对它捆绑的存储区做赋值。

/*
* const关键字演示
* */
#include <stdio.h>
int main() {
int num = 0;
int * const p_num = #
const int *p_num1 = #
*p_num = 10;
printf("num是%d\n", num);
//p_num = NULL; 错误
//*p_num1 = 100; 错误
p_num1 = NULL;
return 0;
}

声明指针的时候可以使用void作为类型名称可以把这种指针叫做无类型指针.这种指针可以和任意类型的存储区捆绑,无法通过这种指针本身知道它捆绑存储区的类型,不应该在这种指针前直接加*操作符也不应该对这种指针做加减整数的计算,这种指针必须首先强制类型转换成有类型指针然后才能使用

/*
* 无类型指针演示
* */
#include <stdio.h>
int main() {
char ch = 'o';
int num = 45;
float fnum = 4.5f;
void *p_v = NULL;
p_v = &ch;
printf("*(char *)p_v是%c\n", *(char *)p_v);
p_v = #
printf("*(int *)p_v是%d\n", *(int *)p_v);
p_v = &fnum;
printf("*(float *)p_v是%g\n", *(float *)p_v);
return 0;
}

所有跨函数使用存储区都是通过指针实现的,数组做形式参数的时候真正的形式参数其实是一个指针

/*
* 跨函数使用存储区演示
* */
#include <stdio.h>
int *read(void) {
static int num = 0;
printf("请输入一个数字:");
scanf("%d", &num);
return #
}
int main() {
int *p_num = read();
printf("数字是%d\n", *p_num);
return 0;
}

声明指针形式参数的时候尽量加上const关键字,无类型指针通常作为形式参数使用

使用存储区的地址做返回值可以让调用函数使用被调用函数的存储区,这个时候被调用函数需要提供一个指针类型的存储区存放作为返回值的地址数据,不可以把非静态局部变量的地址作为返回值使用

标准C语言(8)的更多相关文章

  1. 关于标准C语言的预定义宏【转】

    标准C语言预处理要求定义某些对象宏,每个预定义宏的名称一两个下划线字符开头和结尾,这些预定义宏不能被取消定义(#undef)或由编程人员重新定义.下面预定义宏表,被我抄了下来. __LINE__  当 ...

  2. 【部分原创】标准C语言的优先级、结合性、求值顺序、未定义行为和非确定行为浅析

    零. 优先级    在C++ Primer一书中,对于运算符的优先级是这样描述的:     Precedence specifies how the operands are grouped. It ...

  3. 标准SQL语言的用法

    原文链接:http://www.ifyao.com/2015/05/18/%E6%A0%87%E5%87%86%E7%9A%84sql%E8%AF%AD%E8%A8%80%E4%BD%BF%E7%94 ...

  4. 关于标准C语言的预定义宏

    标准C语言预处理要求定义某些对象宏,每个预定义宏的名称一两个下划线字符开头和结尾,这些预定义宏不能被取消定义(#undef)或由编程人员重新定义.下面预定义宏表,被我抄了下来.__LINE__  当前 ...

  5. UML标准建模语言与应用实例

    一.基本信息 标题:UML标准建模语言与应用实例 时间:2012 出版源:科技创新导报 领域分类:UML标准建模语言 面向对象 系统分析与设计 二.研究背景 问题定义:UML建模语言用图形来表现典型的 ...

  6. UML(统一建模语言)是通用的可视化标准建模语言。由构造块、公共机制、构架三部分组成。

    UML UML(统一建模语言)是通用的可视化标准建模语言.由构造块.公共机制.构架三部分组成. 1.构造块:包括基本的UML建模元素(类.接口.用例等).关系(关联关系.依赖关系.泛化关系.实现关系) ...

  7. 标准C 语言总结

    ***************C语言****************** --day01-- Linux是一个和Windows类似的操作系统 通常通过终端软件使用Linux操作系统 终端软件里只能使用 ...

  8. 标准C语言(1)

    C语言程序的绝大部分内容应该记录在以.c作为扩展名的文件里,这种文件叫源文件,C语言里还包含以.h作为扩展名的文件,这种文件叫做头文件 C语言程序里可以直接使用数字和加减乘除四则运算符号(*代表乘法, ...

  9. 【M35】让自己习惯于标准C++语言

    1.最近一些年C++语言增加的特性有: a.RTTI,namespace,bool,关键字mutable和explicit,enums,以及const static int可以直接初始化. b.扩充了 ...

  10. 标准C语言的输入输出流(i/o)方法详解

    cppreference.com -> 标准 C I/O ->详细说明 标准 C I/O clearerr 语法: #include <stdio.h> void cleare ...

随机推荐

  1. Implementing a Dynamic Vector (Array) in C(使用c实现动态数组Vector)

    An array (vector) is a common-place data type, used to hold and describe a collection of elements. T ...

  2. 【JVM学习笔记】打破双亲委托机制的例子

    Tomcat也有自己的类加载器,比如Servlet,这些类加载器就改变了双亲委托模型的默认机制 (该主题有待深入)

  3. Python简单网络爬虫实战—下载论文名称,作者信息(下)

    在Python简单网络爬虫实战—下载论文名称,作者信息(上)中,学会了get到网页内容以及在谷歌浏览器找到了需要提取的内容的数据结构,接下来记录我是如何找到所有author和title的 1.从sou ...

  4. 【MapReduce】一、MapReduce简介与实例

    (一)MapReduce介绍 1.MapReduce简介   MapReduce是Hadoop生态系统的一个重要组成部分,与分布式文件系统HDFS.分布式数据库HBase一起合称为传统Hadoop的三 ...

  5. 关联规则(Apriori算法)

    关联分析直观理解 关联分析中最有名的例子是“尿布与啤酒”.据报道,美国中西部的一家连锁店发现,男人们会在周四购买尿布和啤酒.这样商店实际上可以将尿布与啤酒放在一块,并确保在周四全价销售从而获利.当然, ...

  6. C++学习笔记-C++对C语言的函数拓展

    内联函数 内联函数是指用inline关键字修饰的函数.在类内定义的函数被默认成内联函数.内联函数从源代码层看,有函数的结构,而在编译后,却不具备函数的性质 inline关键字只是给编译器一个建议,编译 ...

  7. java追加文件

    public class AppendToFile { /** * A方法追加文件:使用RandomAccessFile */ public static void appendMethodA(Str ...

  8. 【Linux 网络编程】REUSADDR

    (1)服务器端尽可能使用REUSEADDR.(2)在绑定之前尽可能调用setsockopt来设置REUSEADDR套接字选项.(3)使用REUSEADDR选项可以使得不必等待TIME_WAIT状态消失 ...

  9. [转帖]docker-compose

    docker-compose https://www.cnblogs.com/embedded-linux/p/10714179.html 需要学习使用一下. 改天自己再改改用过的yaml文件.   ...

  10. powerdesigner去掉网格线

    powerdesigner去掉网格线 去掉网格线