C复习-声明+作用域+链接属性+存储类型

参考: 里科《C和指针》


声明

1)int

short/long/signed/unsigned可以修饰类型。如果有以上的修饰,可以省略int;signed一般只用于char,因为其他整型在默认情况下是有符号数,但char是因编译器而异的。

2)float

只有long double,short/signed/unsigned不可用

3)数组

如果index是用已知的、正确值计算而来的,则无需检查是否合法;如果是根据用户输入的数据产生的,那么使用之前必须检查,以确保在有效范围中。编译器不会检查,要人工编码检查

4)指针

格式:类型 *名称;

为什么使用 int *a; 而非int* a?

因为 int* b, c, d; 并不是声明了3个int指针,而是b是指针,c和d是整型。因此,把类型单独写在前面,*跟随变量名是一种更清楚的写法。这里要声明3个指针应该写作:int *b, *c, *d;

声明一个指针,并用字符串常量初始化:

char *message = "Hello";

typedef:给某个数据类型一个新名字(方便记忆;如果要修改数据类型,直接修改typedef即可)

typedef int *int_pointer;
int_pointer ip; // int_pointer是一个指向int的指针
// 等价于
int *ip;

最好不要用#define创建新的类型名,因为可能无法正确地处理指针。

#define d_ptr_to_char char *
d_ptr_to_char a,b; // 可以正确声明a,但b不对。使用typedef可以直接用 

常量

常量的值是不能修改的,加const即可。

int const a;
const int a; // 两种格式都ok,习惯这个

如何赋值?1)声明时直接初始化;2)函数中声明为const的形参在函数被调用时得到实参的值。

指针:指针的值和所指向的值是两个东西。记忆方法是const只管它右边邻居的值(当然const int和int const一致,看上面)

int *pi; // 指针变量
const int *pci; // 指向整型常量的指针。可以修改指针的值(指向别处),但不能修改它指向的int值
int const *pci; // 同上
int * const cpi; // 指向整型的常量指针。不能修改指针的值,但可以修改它指的int的值
const int* const cpci; // 不能改指向也不能改值// 测试
int a = 1;
int b = 2;
const int *pi = &a;
pi = &b; // 可以修改指向
printf("%d\n", *pi); // 2
//*pi = 3; // 不是可修改的左值,报错。不能修改值
int* const cpi = &a;
*cpi = 3; // 可以修改值,不能修改指向
//cpi = &b; // 不是可修改的左值,报错
printf("%d\n", *cpi); // 3
const int* const cpci = &a; // 必须初始化

#define创建名字常量

#define MAX_ELEMENTS 50;
int const max_elements = 50;

此时使用#define更好,因为只要需要用到字面值常量的地方都可以使用前者,无论是否初始化一个变量。const变量只能用于允许使用变量的地方(虽然数组声明时可以用const作长度)。

使用名字常量的意义在于,它给一个数值起了符号名。尤其在定义数组长度、限制计数次数等情况下,能够提高程序的可维护性:如果一个值需要修改,只修改声明即可,比搜索整个程序修改字面值常量容易得多。

作用域

编译器可以确认4种作用域:文件作用域file scope、函数作用域function scope、代码块作用域block scope和原型作用域prototype scope。作用域的作用:1)域外无法访问 2)不同作用域可以有同名变量、函数。

注意:

  1. 应该避免在嵌套的代码块中出现跟外围变量同名的变量(因为程序只能用内部的值,外部的值被隐藏)。
  2. 如果在函数内声明了跟形参同名的变量,那么形参的值会被隐藏。直接报错了

任何在所有代码块之外声明的标识符都是文件作用域,表示从声明处到文件结尾都可以访问。所以如果在头文件中写了一些常量,这个头文件被include到其他文件后,这些常量也是可以访问的。

原型作用域适用于函数原型(不是函数的定义)中声明的参数名。本来这些参数名不是必须的,也不必跟函数定义中的形参名匹配,

函数作用域适用于语句标签。语句标签是goto用的,这个太少见了。要求是:一个函数中所有的语句标签必须唯一(方便跳转)

链接属性

如果相同的标识符出现在几个不同的源文件中,需要使用链接属性决定如何处理。

1)外部external:不论声明多少次、在几个源文件,都指向同一个实体。在其他语言里也称为全局实体(global)。而且external实体都是静态存储类型。

2)内部internal:在同一个源文件内的所有声明都指向一个实体,但不同源文件的属于不同的

3)无none:没写链接属性,多个声明都是独立的

代码块作用域的变量和函数定义(函数名)缺省是external的,如果希望改成internal,就要在声明前加static关键字。而且static只能在缺省是external时才能改变链接属性,比如e即使声明static也不是external的。

typedef char *a;
int b; // 默认external
int c( int d) // c默认external
{int e;int f( int g ); // f默认external
}

如果希望把某个某个标识符指定为external,那应该在第一次声明时使用extern关键字。如果在第2次或以后声明时采用,不会改变第一次声明时指定的链接属性。

static int i;
int func() {extern int i; // 实际还是internal的
}

文件作用域的变量其实不用指定static还是extern,但是可以用,这样看起来更清晰。

存储类型storage class

指存储变量值的内存类型,决定了变量何时创建、何时销毁及值保持多久。存储变量的位置有:1)普通内存 2)运行时的堆栈 3)硬件寄存器

变量的缺省存储类型取决于声明位置:

1)在任何代码块外声明的变量存储在静态内存中,不属于堆栈,称为静态变量static。这些变量不能指定存储类型,是在程序运行之前创建的,在整个执行期间始终存在且保持值不变,除非给它赋值或程序结束。函数的存储类型无所谓,反正总是存储在静态内存中

2)在代码块内部声明的变量缺省存储类型是自动automatic,是存储在堆栈中的,称为自动变量auto。它在声明时才创建,代码块结束后销毁。如果加上关键字static,可以使之变成静态(指会一直存在,但不能改变链接属性,即作用域)。函数的形参不能声明为static(因为要传值啊)

3)register可以声明寄存器变量,表示存储机器的硬件寄存器而不是内存中。通常寄存器变量比在内存的访问效率更高,但是编译器不一定会执行(有自己的优化方法),因为如果有太多变量被声明为register,它可能只挑几个存储到寄存器,其余仍然跟auto一样存在堆栈。虽然寄存器变量的创建与销毁时间跟auto相同,但是常需要做额外工作,比如恢复先前存储的值(又用到堆栈),因此将指针或者函数的形参声明为register未必能节省很多时间

静态变量是在可执行文件载入内存时,变量就有正确的值了,如果没有显式初始化,则会初始化为0(初始化只有一次);但是自动变量的初始化开销大,除非显式初始化,不然创建后它的值都是垃圾。

作用域、存储类型实例

int a = 5; // a是external的,其他文件
extern int b; // 如果b定义在其他地方,类似a,此时extern不必须,但是加上可以体现
static int c; // c本来external,现在别的文件不能使用了
// a,b,c的存储类型都是静态,即存储在静态内存中int d(int e) // d在缺省的情况下是external,所以其他源文件只要声明,就可以调用d
{int f = 15;register int b;static int g = 20; // 定义为static后初始化一次,后续不再初始化extern int a; // extern没必要,因为仍然在第一行的作用域内...{int e; // 形参e被屏蔽,是autoint a; // autoextern int h; // 为了访问全局变量h,必须使用extern关键字,否则是局部变量...}...{int x, e;}...
}static int i(){} // 是internal,其他源文件不可调用。d不能调用i,因为d前没有i的声明

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

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

相关文章

计算机基础知识33

进程基础(操作系统中的概念) 进程它是操作系统总最重要的概念,线程也是 进程和线程都是有操作系统来调度使用的,我们程序员是不能控制的 # 进程和程序是两码事、完全不一样 程序:其实一个死的东西、一堆代码就是程序,它也没有生命…

C++ UDP通信

#pragma once #ifndef XUDP_H #define XUDP_H#ifdef WIN32 #include <windows.h> #define socklen_t int #else #include <arpa/inet.h> #define closesocket close //替换close函数 #include <unistd.h>#include<iostream> #endifclass XUdp { pub…

源代码审计(白盒测试)

1.简介 代码安全测试是从安全的角度对代码进行安全测试评估 2.测试的方法 人工审核和静态分析工具辅助进行 人工审核&#xff1a;既能解决内部问题也能解决外部问题。是目前最有效率的解决方案&#xff0c;并且在理论上手工代码审核是非常有效的&#xff0c;但人工审核的效率不…

element表格实现单选框

利用checkbox来实现表格单选,思路就是将checkbox的值绑定到当前行mainFlag,定义checkbox的change事件,每当值改变时将上次选中的行数据mainFlag改给false <template><el-table:data"tableData"style"width: 100%"><el-table-column label&q…

视频推拉流/直播点播平台EasyDSS分享的链接提示“无信号”,该如何解决?

视频直播点播平台EasyDSS可支持用户自行上传视频文件&#xff0c;也可将上传的点播文件作为虚拟直播进行播放。平台能支持多屏播放&#xff0c;可兼容Windows、Android、iOS、Mac等操作系统&#xff0c;还能支持CDN转推&#xff0c;具备较强的可拓展性与灵活性。 为给用户提供更…

Git 提交规范

遇到的问题 在项目中采用 git 管理代码版本时&#xff0c;突然不能进行提交&#xff08;git commit&#xff09;。 报错信息如下&#xff1a; ERROR invalid commit message format. Proper commit message format is required for automated changelog generation. Git 规范…

AI 浪潮下的创业故事(一)—— Jina AI

点击蓝字 关注我们 编辑&#xff1a;Alan Wang 排版&#xff1a;Rani Sun 微软 Reactor 为帮助广开发者&#xff0c;技术爱好者&#xff0c;更好的学习 .NET Core, C#, Python&#xff0c;数据科学&#xff0c;机器学习&#xff0c;AI&#xff0c;区块链, IoT 等技术&#xff0…

SaaS 完整指南

什么是软件即服务 (SaaS)&#xff1f; 软件即服务 (SaaS) 是云计算的三个组成部分之一&#xff0c;是一种软件分发模型&#xff0c;其中第三方提供商托管应用程序&#xff0c;最终用户可以通过 Internet 访问软件。 SaaS 应用程序开发使组织无需在自己的计算机或自己的数据中…

CentOS7 内核升级

1.linux内核版本说明 https://en.wikipedia.org/wiki/Linux_kernel_version_history The Linux Kernel Archives - Releases

【Python】Python 实现 Excel 到 CSV 的转换程序

Python 实现 Excel 到 CSV 的转换程序 Excel 可以将电子表格保存为 CSV 文件&#xff0c;只要点几下 鼠标&#xff0c;但如果有几百个 Excel文件要转换为 CSV &#xff0c; 就需要点击几小时。利用 openpyxl 模块&#xff0c; 编程读取当前工作目录中的所有 Excel 文件&#x…

Mobpush智能化精准推送,助力求职者快人一步

近日&#xff0c;“BOSS”直聘崩了的消息又又又上了热搜&#xff0c;2023年9月15日上午&#xff0c;BOSS直聘在线统计超过4700万人。由此可见&#xff0c;随着金九银十招聘旺季的到来&#xff0c;求职软件成为人们的青睐。但是对于大多数使用招聘软件的用户而言&#xff0c;往往…

unigui点击按钮后弹出悬浮窗,几秒钟后关闭

为了实现点击按钮后&#xff0c;复制内容到剪切板&#xff0c;然后弹出悬浮窗提示给用户。 js代码如下&#xff0c;复制内容&#xff0c;然后保存命名为.js的文件&#xff1a; //弹窗提醒function showAlert(s_msg) {// 创建 div 元素var div document.createElement("d…

【算法训练-排序算法 三】【排序应用】合并区间

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【合并区间】&#xff0c;使用【数组】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为&…

【vr】【unity】白马VR课堂系列-VR开发核心基础05-主体设置-手柄对象的引入和设置

【视频教学】 【白马VR课堂系列-VR开发核心基础05-主体设置-手柄对象的引入和设置】 https://www.bilibili.com/video/BV19D4y1N73i/?share_source=copy_web&vd_source=7f5c96f5a58b7542fc6b467a9824b04e 【内容】 上一节引入了XR Origin并进行了初步设置,运行测试时V…

数据库主从切换过程中Druid没法获取连接错误

背景&#xff1a; 今天dba在进行DB的主从切换&#xff0c;导致应用一直报错&#xff0c;获取不到DB连接&#xff0c;druid的错误信息如下&#xff1a; Could not open JDBC Connection for transaction; nested exception is com.alibaba.druid.pool.GetConnectionTimeoutExc…

基于主动移频法与AFD孤岛检测的单相并网逆变器matlab仿真

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 仿真模型 算法介绍 (1)仿真模型由单相电网、逆变器、滤波环节、PI控制器、PWM生成器、锁相环、AFD控制器s函数、测量模块等构成&#xff1b; (2)采用主动移频法(AFD)进行孤岛检测&#xff1b; (3)相应速度…

CMake教程-第 7 步:添加系统自省功能

CMake教程-第 7 步&#xff1a;添加系统自省功能 1 CMake教程介绍2 学习步骤Step 1: A Basic Starting PointStep 2: Adding a LibraryStep 3: Adding Usage Requirements for a LibraryStep 4: Adding Generator ExpressionsStep 5: Installing and TestingStep 6: Adding Sup…

基于springboot实现汉服文化分享平台项目【项目源码+论文说明】

摘要 本论文主要论述了如何使用JAVA语言开发一个汉服文化平台网站 &#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述汉服文化平台网站的当前背景以及系统开发的…

【Linux常用命令12】搜索命令及特殊字符的使用

which&#xff1a;查看可执行文件的位置 which 命令whereis&#xff1a;查看文件的位置&#xff0c;只能用于程序名的搜索 whereis [选项] 命令 -b 定位可执行文件。 -m 定位帮助文件。 -s 定位源代码文件。 -u 搜索默认路径下除可执行文件、源代码文件、帮助文件以外…

Python 中的省略号对象

作为一名经验丰富的 Python 开发人员&#xff0c;您可能遇到过 Python 中的三个点…省略号对象。 如果您尝试在 Python 解释器中打印此内容&#xff0c;它将显示一个省略号。 本篇文章将介绍 Python 中省略号对象的使用。 使用省略号作为未编写代码的占位符 省略号对象可以以…