<<c和指针>>温故及问题研讨(第三章)

news2024/10/5 13:47:50

第三章-数据

  • 1. 前言
  • 2. 基本数据类型
    • 2.1 整型家族
    • 2.2 字面值常量
  • 3. 基本声明
    • 3.1 数组的声明以及引用
    • 3.2 指针的声明注意事项
    • 3.3 隐式声明
  • 4. 常量
  • 5. 作用域
    • 5.1 代码块作用域
    • 5.2 文件作用域
    • 5.3 原型作用域
  • 6. 链接属性
    • 6.1 链接属性分类以及作用范围
    • 6.2 关键字:extern和static
      • 6.21 static
      • 6.22 extern
      • 6.3 static关键字的总结
  • 7. 总结


1. 前言

这篇文章向大家分享<<C和指针>>第三章的内容–数据,这篇文章在专栏:书籍分享中,有兴趣关于<<C和指针>>的朋友可以来浏览一下.和之前一样,我分享的内容是我认为容易被忽略的点,和C语言中更接近于底层的一些逻辑.有些内容我在C语言的学习中已经分享过了的,我会给出之前的博客链接并且跳过这一段.



2. 基本数据类型

2.1 整型家族

我们在之前的分享中已经大致介绍过了整型家族c语言分享,这里我再做一点补充:首先是我们的范围问题,我们给出所有整型家族变量的范围:

在这里插入图片描述


我们在阅读一些文献的时候,时常会遇见一个返回类型: size_t ,比如我们在cplusplus上搜索strlen函数时:

在这里插入图片描述 这里的 size_t 等同于 unsigned int .



2.2 字面值常量

这里我们引出字面值常量的概念,因为后面又很多定义都会涉及到这个 “字面值常量”.
字面值这个术语是字面值常量的缩写——这是一种实体,指定了自身的值,并且不允许发生改变。这个特点非常重要,因为ANSI C允许命名常量(named constant,声明为const的变量)的创建,它与普通变量极为类似。
区别在于,当它被初始化以后,它的值便不能改变



3. 基本声明

3.1 数组的声明以及引用

在我们声明一个数组values之后

int values[20]={0};

数组的下标总是从0开始,最后一个元素的下标是元素的数目减1。我们没有办法修改这个属性,但如果你一定要让某个数组的下标从10开始,那也并不困难,只要在实际引用时把下标值减去10即可。

C数组另一个值得关注的地方是: 编译器并不检查程序对数组下标的引用是否在数组的合法范围之内。 这种不加检查的行为有好处也有坏处。好处是不需要浪费时间对有些已知是正确的数组下标进行检查。坏处是这样做将使无效的下标引用无法被检测出来。 所以我们可以养成一个良好的习惯:在使用数组下标前进行检查,确保它们位于有效范围之内



3.2 指针的声明注意事项

当我们这样定义指针变量时:

int* b,c,d;

人们很自然地以为这条语句把所有三个变量声明为指向整型的指针,但事实上并非如此。我们被它的形式愚弄了。 星号实际上是表达式 * b的一部分,只对这个标识符有用。 这里只有b是一个指针,但其余两个变量只是普通的整型。要声明三个指针,正确的语句如下

int* b,*c,*d;


3.3 隐式声明

C语言中有几种声明,它的类型名可以省略。例如,==函数如果不显式地声明返回值的类型,它就默认返回整型。当你使用旧风格声明函数的形式参数时,如果省略了参数的类型,编译器就会默认它们为整型。==比如这个地方:

f(x)
{
   return x+1; 
}

函数f缺少返回类型,于是编译器就默认它返回整型。参数x也没有类型名,同样被默认为整型。

提醒:依赖隐式声明可不是一个好主意。隐式声明总会在读者的头脑中留下疑问:是有意遗漏类型名呢?还是不小心忘记写了?显式声明就能够清楚地表达你的意图



4. 常量

我们之前提过用const修饰的变量会变成常量,当我们这里涉及到指针的时候就容易混淆起来, 因为有两样东西都有可能成为常量–指针变量和和它所指向的实体,下面是几个声明的例子 :

int* pi;//这里pi是普通的指针变量
int const *pi;//这里pi是一个指向整型常量的指针.你可以修改指针的值,但是不能修改它所指向的值
int* const pi;//这里pi是一个指向整型的常量指针.此时指针是常量,它的值无法修改,但是我可以修改它指向的整型值
int const *const pi;//最后这里无论是指针本身还是它指向的值都是常量都不能修改.

这四种是完全不一样的定义方式,看到这儿你可能会有一点迷糊,下面我们用一段代码来演示一下:

int x=1,y=2,z=3;
int const *a=&x;
 a=&y;//这种写法是允许的
 *a=2;//这种写法是不允许的
int *const b=&y;
 b=&x;//这种写法是不允许的
 *b=1;//这种写法是允许的
 int const *const c=&z;//这种写法都不能变


5. 作用域

当变量在程序的某个部分被声明时,它只有在程序的一定区域才能被访问。这个区域由标识符的作用域(scope)决定。标识符的作用域就是程序中该标识符可以被使用的区域。 例如,函数的局部变量的作用域局限于该函数的函数体 这个规则意味着两点。首先,其他函数都无法通过这些变量的名字访问它们,因为这些变量在它们的作用域之外便不再有效。其次,只要分属不同的作用域,你可以给不同的变量起同一个名字。

编译器可以确认4种不同类型的作用域——文件作用域、函数作用域、代码块作用域和原型作用域。标识符声明的位置决定它的作用域。 我们下面给出这些作用域的定义,后面我们会用到



5.1 代码块作用域

我们经常听说一个词:代码块,代码块.那么代码块到底是什么?这里给出它的定义,后面会经常看见它:

位于一对花括号之间的所有语句称为一个代码块。任何在代码块的开始位置声明的标识符都具有代码块作用域(block scope),表示它们可以被这个代码块中的所有语句访问。
这里包括我们的分支与循环语句的{},函数的{},甚至于main函数的{},以及你自己写出来的{}.

在K&R C中,函数形参的作用域开始于形参的声明处,位于函数体之外。如果在函数体内部声明了名字与形参相同的局部变量,它们就将隐藏形参。

但是ANSI C扼止了这种错误的可能性,它把形参的作用域设定为函数最外层的那个作用域(也就是整个函数体)。这样,声明于函数最外层作用域的局部变量无法和形参同名,因为它们的作用域相同。 也就是说我们的函数的形参名可以和实参名相同

如果你想深入了解K&R C和ANSL C,请跳转K&R C与ANSI C的区别



5.2 文件作用域

任何在所有代码块之外声明的标识符都具有文件作用域(file scope), 它表示 这些标识符从它们的声明之处直到它所在的源文件结尾处都是可以访问的。 在文件中定义的函数名也具有文件作用域,因为函数名本身并不属于任何代码块。我应该指出,在头文件中编写并通过#include指令包含到其他文件中的声明就好像它们是直接写在那些文件中一样。它们的作用域并不局限于头文件的文件尾。 ,也就是说我们包含的头文件的作用域是在我们自己写的文件当中结束.



5.3 原型作用域

原型作用域(prototype scope)只适用于在函数原型中声明的参数名。 在原型中(与函数的定义不同),参数的名字并非必需。但是,如果出现参数名,你可以随你所愿给它们取任何名字,它们不必与函数定义中的形参名匹配,也不必与函数实际调用时所传递的实参匹配。原型作用域防止这些参数名与程序其他部分的名字冲突。事实上,唯一可能出现的冲突就是在同一个原型中不止一次地使用同一个名字。



6. 链接属性

链接属性一共有3种——external(外部)、internal(内部)和none(无)。没有链接属性的标识符(none)总是被当作单独的个体,也就是说该标识符的多个声明被当作独立不同的实体。 属于internal链接属性的标识符在同一个源文件内的所有声明中都指同一个实体,但位于不同源文件的多个声明则分属不同的实体 最后,属于external链接属性的标识符不论声明多少次、位于几个源文件都表示同一个实体。 ,我们用一个图来进一步说明:


6.1 链接属性分类以及作用范围

在这里插入图片描述

图3.2的程序骨架通过展示名字声明的所有不同方式,描述了链接属性。在缺省情况下,标识符b、c和f的链接属性为external,其余标识符的链接属性则为none因此,如果另一个源文件也包含了标识符b的类似声明并调用函数c,它们实际上访问的是这个源文件所定义的实体。 f的链接属性之所以是external是因为它是个函数名。在这个源文件中调用函数f,它实际上将链接到其他源文件所定义的函数,甚至这个函数的定义可能出现在某个函数库。


6.2 关键字:extern和static

再一个:关键字 extern 和 static 用于在声明中修改标识符的链接属性。 如果某个声明在正常情况下具有external链接属性,在它前面加上static关键字可以使它的链接属性变为internal。 例如,如果第2个声明像下面这样书写:

6.21 static

static int b;

那么变量b就将为这个源文件所私有.在其他源文件中,如果也链接到一个叫做b的变量,那么它所引用的是宁外iyig不同的变量.类似的你也可以把函数声明为static,如下:

static int c(int d)

这样可以防止它被其他源文件调用

值得注意的是static只对缺省链接属性为external的声明才有改变链接属性的效果。例如,尽管你可以在声明5前面加上static关键字,但它的效果完全不一样,因为e的缺省链接属性并不是external。

6.22 extern

extern关键字的规则更为复杂。一般而言,它为一个标识符指定external链接属性,这样就可以访问在其他任何位置定义的这个实体。请考虑图3.3的例子。 声明3为k指定external链接属性。这样一来,函数就可以访问在其他源文件声明的外部变量了。也就是可以访问其他源文件中定义的k

在这里插入图片描述

当extern关键字用于源文件中一个标识符的第1次声明时,它指定该标识符具有external链接属性。但是,如果它用于该标识符的第2次或以后的声明时,它并不会更改由第1次声明所指定的链接属性。 例如,图3.3中的声明4并不修改由声明1所指定的变量i的链接属性。


6.3 static关键字的总结

当用于不同的上下文环境时,static关键字具有不同的意思。确实很不幸,因为这总是给C程序员新手带来混淆。本节对static关键字作了总结,应该能够帮助你搞清这个问题。

  1. 当它用于函数定义时,或用于代码块之外的变量声明时,static关键字用于修改标识符的链接属性,从external改为internal,但标识符的存储类型和作用域不受影响。用这种方式声明的函数或变量只能在声明它们的源文件中访问。

  1. 当它用于代码块内部的变量声明时,static关键字用于修改变量的存储类型,从自动变量修改为静态变量,但变量的链接属性和作用域不受影响。用这种方式声明的变量在程序执行之前创建,并在程序的整个执行期间一直存在,而不是每次在代码块开始执行时创建,在代码块执行完毕后销毁。


7. 总结

  1. 在声明指针变量时不要采用容易误解的写法
  2. 不要误解指针声明中初始化的含义
  3. 不要依赖隐式声明
  4. 用const声明其值不会改变的变量
  5. 不要在嵌套的代码块之间使用相同的变量名
  6. 除了实体的具体定义位置外,在它的其他声明位置都要使用extern关键字

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/463217.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据库基础篇 《18.MySQL8其它新特性》

第18章_MySQL8其它新特性 1. MySQL8新特性概述 MySQL从5.7版本直接跳跃发布了8.0版本&#xff0c;可见这是一个令人兴奋的里程碑版本。MySQL 8版本在功能上做了显著的改进与增强&#xff0c;开发者对MySQL的源代码进行了重构&#xff0c;最突出的一点是多MySQL Optimizer优化…

GPT详细安装教程-GPT软件国内也能使用

GPT (Generative Pre-trained Transformer) 是一种基于 Transformer 模型的自然语言处理模型&#xff0c;由 OpenAI 提出&#xff0c;可以应用于各种任务&#xff0c;如对话系统、文本生成、机器翻译等。GPT-3 是目前最大的语言模型之一&#xff0c;其预训练参数超过了 13 亿个…

LeetCode:206. 反转链表

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; &#x1f33b;算法&#xff0c;不如说它是一种思考方式&#x1f340; 算法专栏&#xff1a; &#x1f449;&#x1f3fb;123 一、&#x1f331;206. 反转链表 题目描述&#xff1a;给你单链表的头节点 head &#x…

Sharding-JDBC之垂直分库水平分表

目录 一、简介二、maven依赖三、数据库3.1、创建数据库3.2、订单表3.3、用户表 四、配置&#xff08;二选一&#xff09;4.1、properties配置4.2、yml配置 五、实现5.1、实体5.2、持久层5.3、服务层5.4、测试类5.4.1、保存订单数据5.4.2、查询订单数据5.4.3、保存用户数据5.4.4…

Android SeekBar控制视频播放进度(二)——seekTo()不准确

Android SeekBar控制视频播放进度二——seekTo不准确 简介seekTo()视频帧 和 视频关键帧解决办法方法一方法二 简介 上一篇文章中&#xff0c;我们介绍了使用SeekBar控制视频播放&#xff0c;使用过程中发现&#xff0c;对于一些视频&#xff0c;我们拖动SeekBar进度条调节播放…

喜报 | ScanA内容安全云监测获评“新一代信息技术创新产品”

4月20日&#xff0c;在赛迪主办的2023 IT市场年会上&#xff0c;“年度IT市场权威榜单”正式发布。 知道创宇的ScanA内容安全云监测产品荣获“新一代信息技术创新产品”奖项。作为中国IT业界延续时间最长的年度盛会之一&#xff0c;历届IT市场年会公布的IT市场权威榜单已成为市…

备份数据看这里,免费教你苹果手机怎么备份所有数据!

案例&#xff1a;苹果手机怎么算备份成功&#xff1f; 【友友们&#xff0c;手机恢复出厂设置前&#xff0c;怎么样可以备份苹果手机里面的所有数据&#xff1f;】 苹果手机备份数据对于用户来说是非常重要的。在备份数据的同时&#xff0c;还需要学会如何恢复误删的数据。那么…

【微服务笔记22】微服务组件之Sentinel控制台的使用(Sentinel Dashboard)

这篇文章&#xff0c;主要介绍微服务组件之Sentinel控制台的使用&#xff08;Sentinel Dashboard&#xff09;。 目录 一、Sentinel控制台 1.1、下载Dashboard控制台 1.2、搭建测试工程 &#xff08;1&#xff09;引入依赖 &#xff08;2&#xff09;添加配置信息 &#…

微服务生态 -- dubbo -- dubbo3应用级别服务发现(阅读官方文档)

服务发现概述 从 Internet 刚开始兴起&#xff0c;如何动态感知后端服务的地址变化就是一个必须要面对的问题&#xff0c;为此人们定义了 DNS 协议&#xff0c;基于此协议&#xff0c;调用方只需要记住由固定字符串组成的域名&#xff0c;就能轻松完成对后端服务的访问&#x…

236. 二叉树的最近公共祖先【190】

难度等级&#xff1a;中等 上一篇算法&#xff1a; 103. 二叉树的锯齿形层序遍历【191】 力扣此题地址&#xff1a; 236. 二叉树的最近公共祖先 - 力扣&#xff08;Leetcode&#xff09; 1.题目&#xff1a;236. 二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点…

【MySQL】数据表的增删查改

1、CRUD的解释 C&#xff1a;Create增加 R&#xff1a;Retrieve查询 U&#xff1a;Update更新 D&#xff1a;Deleta删除 2、添加数据 2.1 添加一条记录 添加数据是对表进行添加数据的&#xff0c;表在数据库中&#xff0c;所以还是得先选中数据库&#xff0c;选中数据库还在进行…

STM32F429移植microPython笔记

目录 一、microPython下载。二、安装开发环境。三、编译开发板源码。四、下载验证。 一、microPython下载。 https://micropython.org/download/官网 下载后放在linux中。 解压命令&#xff1a; tar -xvf micropython-1.19.1.tar.xz 二、安装开发环境。 sudo apt-get inst…

MUSIC算法仿真

DOA波达方向估计 DOA&#xff08;Direction Of Arrival&#xff09;波达方向是指通过阵列信号处理来估计来波的方向&#xff0c;这里的信源可能是多个&#xff0c;角度也有多个。DOA技术主要有ARMA谱分析、最大似然法、熵谱分析法和特征分解法&#xff0c;特征分解法主要有MUS…

HTML+CSS+JS 学习笔记(四)———jQuery

&#x1f331;博客主页&#xff1a;大寄一场. &#x1f331;系列专栏&#xff1a;前端 &#x1f331;往期回顾&#xff1a; &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注​​ 目录 jQuery 基础 jQuery 概述 下载与配置jQuery 2. 配置jQuery jQuery 选…

数据库管理-第七十期 自己?自己(20230425)

数据库管理 2023-04-25 第七十期 自己&#xff1f;自己1 自己吓自己2 自己坑自己3 自己挺自己4 自己懵自己总结 第七十期 自己&#xff1f;自己 来到70了&#xff0c;最近有点卷&#xff0c;写的稍微多了些。 吐槽一下五一调休&#xff0c;周末砍一天&#xff0c;连6天&#x…

重学Java第一篇——数组

本片博客主要讲述了以下内容&#xff1a; 1、 一维数组和二维数组的创建和初始化方式&#xff1b; 2、数组的遍历和赋值 3、java.util.Arrays的常用方法 4、数组在内存中的分布&#xff08;图示&#xff09; 创建数组和初始化 type[] arr_name;//方式一 type arr_name[];//方式…

一家传统制造企业的上云之旅,怎样成为了数字化转型典范?

众所周知&#xff0c;中国是一个制造业大国。在想要上云以及正在上云的企业当中&#xff0c;传统制造企业也占据了相当大的比例。 那么这类企业在实施数字化转型的时候&#xff0c;应该如何着手&#xff1f;我们不妨来看看一家传统制造企业的现身说法。 国茂股份的数字化转型诉…

云原生-如何部署k8s集群与部署sms集群

阿里云开通三台云服务器实例&#xff0c;&#xff08;同一个vpc下&#xff09;&#xff0c;配置安全组入规则&#xff0c;加入80端口 ssh登录三台云服务器 在三台云服务器上部署容器环境&#xff08;安装docker&#xff09;&#xff08;https://www.yuque.com/leifengyang/oncl…

Springboot Mybatis使用pageHelper实现分页查询

以下介绍实战中数据库框架使用的是mybatis&#xff0c;对整合mybatis此处不做介绍。 使用pageHelper实现分页查询其实非常简单&#xff0c;共两步&#xff1a; 一、导入依赖&#xff1b; 二、添加配置&#xff1b; 那么开始&#xff0c; 第一步&#xff1a; pom.xml添加依…

工具链和其他-超级好用的web调试工具whistle

目录 whistle介绍 整体结构 能力 规则 6个使用场景示例 1.修改Host 2.代理 3.替换文件&#xff08;线上报错时&#xff09; 4.替换UA 5.远程调试 6.JS注入 互动 whistle介绍 整体结构 安装&#xff1a; npm install whistle -g cli&#xff1a;whistle help 启动…