来自<c primer plus >的随记

c primer plus 的学习笔记,主要从数组和指针开始


//数组元素是变量(除非被声明为const),但是数组名不是变量。

//如果不修改字符串,不要用指针指向字符串字面量。
//如果要用数组表示一系列待显示的字符串,请使用指针数组,效率高。如果要改变字符串或为字符串输入预留空间,不要使用指向字符串字面量的指针。
//计算机不会在读取字符串时顺便计算它的长度,然后再分配空间。
char *name;
scanf("%s,name");
name可能会擦写程序中的数据或代码。
//空字符是标记c字符串末尾的字符
空指针是一个值,函数使用它返回一个有效地址表示某些特殊情况。
//gets读取整行输入,直至遇到换行符,丢弃它,在字符末尾添加一个空字符使其成为c字符串。如果输入的字符串过长会导致缓冲区溢出
//fgets()专门设计用于处理文件输入。
//scanf以下一个空白字符(空行 空格 制表符 换行符)作为字符串的结束。
//puts在显示字符串时会自动在其末尾添加一个换行符。必须确保有空字符使其停止输出。
//gets()丢弃输入中的换行符,但是puts()在输出中添加换行符。另一方面,fgets()保留输入中的换行符,fputs()不会在输出中添加换行符。
puts()应与gets()配对使用,fputs()应与fgets()配对使用。gets()已经被废弃。
//与puts不同的是,printf()不会自动在每个字符末尾加上一个换行符,因此必须在参数中指明在哪里使用换行符。
//被储存的每个值都占用一定的物理内存,这样一块内存成为对象,面向对象编程中的对象指的是类对象,其定义包括数据和允许对数据进行的操作,c不是面向对象编程语言。
//const char * pc="Behold a string literal!";
const只能保证被pc指向的字符串内容不被修改,但是无法保证pc不指向别的字符串。
//注意翻译单元和文件!
//变长数组必须是自动存储类别,这意味着无论在函数中声明还是作为函数形参声明,都不能使用static和extern存储类别说明符,而且不能在声明中初始化他们。
//变长数组中的“变”不是指可以修改已创建的数组的大小,一旦创建了变长数组,它的大小则保持不变。这里的“变”指的是:在创建数组时,可以使用变量指定数组的维度。
//带变长数组形参的函数实际上是在原始数组中处理数组,因此可以修改传入的数组。
//变长数组还允许动态内存分配,这说明可以在程序运行时指定数组的大小。普通c数组都是静态内存分配,即在编译时确定数组的大小。
它的存储器从声明处到块的末尾,而不是从块的开始处到块的末尾。
//复合字面量是匿名的,所以不能先创建然后再使用它。必须在创建的同时使用它。它是提供只临时需要的值的一种手段,具有块作用域。
//块作用域变量也能具有静态存储期,为了创建这样的变量,要把变量声明在块中,且在声明前面加上关键字static。
//寄存器变量储存在cpu的寄存器中,访问和处理这些变量的速度更快。由于其非储存在内存中,所以无法获取其地址,都是块作用域、无链接和自动存储期。可声明为register的数据类型有限(如double不行太大了)。
//不能在函数的形参中使用static。
//外部链接的静态变量具有文件作用域、外部链接和静态存储期。如果一个源代码文件使用的外部变量定义在另一个源代码文件中,则必须用extern在该文件声明该变量。
//在执行块中的语句时,块作用域中的变量将“隐藏”文件作用域中的同名变量。
//与自动变量不同,如果未初始化外部变量,它们会被自动初始化为0.并且只能使用常量表达式初始化文件作用域变量。例如下面错误的例子 int x2 = 2 * x;//x是变量。
//定义式声明和引用式声明。
一个变量只能有一个定义式声明,但是带extern的声明是引用式声明,可以有多个。
//不要用关键字extern创建外部定义,只用它来引用现有的外部定义。
假设这样写:
extern int tern;
int main(void)
{}
编译器会假设tern实际的定义在该程序的别处,该声明不会引起分配存储空间。
//内部链接的静态变量只能用于同一个文件中的函数。
//在同一个文件所有函数的外部声明的变量是外部变量,如果在这种声明前面加上关键字static,那么其声明的变量具有文件作用域、内部链接和静态存储期。
//函数也有存储类别,可以是外部函数(默认)或静态函数。
//用static定义的变量具有静态存储期、文件作用域和内部链接。
//静态数据在程序载入时分配内存,而自动数据在程序执行块时分配。
//在ANCSI C中,应该坚持使用强制类型转换,提高代码可读性。然而指向void的指针赋给任意类型的指针完全不用考虑类型匹配的问题。
//三种创建数组的方法
1、声明数组时,用常量表达式表示数组的维度,用数组名访问数组的元素。可以用静态内存或自动内存创建这种数组。
2、声明变长数组时,用变量表达式表示数组的维度,用数组名访问数组的元素。具有这种特性的数组只能在自动内存中创建。
3、声明一个指针,调用malloc(),将其返回值赋给指针,使用指针访问数组的元素。该指针可以是静态的或动态的。
例如:
double * ptd;
ptd = (double *) malloc(n * sizeof(double));
使用malloc(),程序可以在运行时才确定数组大小。
//动态分配的内存数量只会增加,除非用free()释放。
//在函数末尾处调用free()函数可避免“内存泄漏”的问题发生。
//calloc()函数把块中的所有位都设置为0(并不是所有硬件系统都这样)。同样可以用free()释放。
//变长数组是自动存储类型,不必用free()。但是malloc()不必局限在一个函数访问。
//静态存储类别程序执行时被创建,程序结束时被销毁。 自动存储类别进入变量定义所在块时存在,在程序离开块时消失。这部分内存通常作为“栈”来处理。 动态分配的内存在调用malloc()等函数存在,未使用的内存块分散在已使用的内存块之间,同时使用动态内存通常比使用栈慢。
总而言之,程序把静态对象、自动对象和动态分配的对象存储在不同的区域。
//c90新增了两个属性:恒常性(constancy)和易变形(volatility)。分别用关键字const和volatile来声明,c99标准新增了第3个限定符:restrict。用于提高编译器优化。
//简而言之,const放在*左侧任意位置,限定了指针指向的数据不能改变;const放在*的右侧,限定了指针本身不能改变。常见用法时声明为函数形参的指针保护数组数据。
//用const限定符声明全局数据很合理。
//在文件间共享const数据要小心。可以采用两个策略。第一,遵循外部变量的常用规则,即在一个文件中使用定义式声明,在其他文件中使用引用式声明。
//volatile限定符告知计算机,代理(而不是变量所在的程序)可以改变该变量的值。它涉及编译器优化。详见书。
//restrict关键字允许编译器优化某部分代码以更好地支持计算,它只能用于指针,表明该指针是访问数据对象的唯一且初始的方式。
//_Atomic  通过各种宏函数来访问原子类型,当一个线程对一个原子类型的对象执行原子操作时,其他线程不能访问该对象。
//c99允许把类型限定符和存储类别说明符static放在函数原型和函数头的形式参数的初始化括号中。
static情况不同,新的用法告知编译器如何使用形式参数。
//链接描述定义在程序某翻译单元中的变量可被链接的程度。
//C的5中存储类别(不包括线程的概念)
自动 | 寄存器 | 静态、无链接 | 静态、外部链接 | 静态、内部链接
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值