龙空技术网

《C语言》-(学习笔记2)

kawhi莱昂纳德 71

前言:

此刻你们对“c语言连接器返回错误代码1是什么意思”都比较着重,兄弟们都需要知道一些“c语言连接器返回错误代码1是什么意思”的相关内容。那么小编同时在网摘上搜集了一些关于“c语言连接器返回错误代码1是什么意思””的相关内容,希望大家能喜欢,看官们一起来学习一下吧!

CH6—函数

函数声明:

返回值类型 函数名 (形式参数1,形式参数2);

函数定义:

返回值类型 函数名 (形式参数1,形式参数2) {语句}

函数调用:

函数名(实参1,实参2);

递归:

优点:为某些编程问题提供了最简单的解决方案。

缺点:一些递归算法会快速消耗计算机的内存资源

初识指针:

定义时,*和指针之间的空格,通常来说在声明时使用空格,在解引用变量时省略空格;

CH10—数组和指针

数组:

1;使用数组前必须先初始化,必须要先赋初值,如果不赋值,编译器使用的是内存上相应位置的值。

2;初始化的项数和数组的大小要一致,初始化列表中的值少于元素个数,编译器会把剩余的元素初始化为0,如果不初始化数组,所有的元素都是垃圾值,

3;如果初始化列表的项数多余数组元素个数,编译器会认为出错。

4;可以省略方括号中的数字,编译器可以自动匹配数组的大小和初始化列表中的项数。

二维数组:

初始化1;int arr = {1,2,3,4};

初始化2;int arr = {{1,2}, {3,4}};

数组和指针关系:

区分:

*(arr+2) arr数组第三个元素的值

*arr +2 arr数组第一个元素的值+2

函数、数组和指针关系:

int sum (int arr [], int n);

注意:只能在函数原型或函数定义中,可以用int arr[]代替int *arr;而且int arr[],提醒读者指针arr指向的不仅仅是一个int类型的指针,而且还是一个int类型数组的元素。由于数组名是该数组首元素的地址,作为实际参数传参时,则以下四种原型是等价的:

Int sum (int *arr, int n);

Int sum (int *, int);

Int sum (int arr [], int n);

Int sum (int [], int);

使用注意:

1、当arr为数组名时,不可以使用arr++这种表达式地址应当和指针类型兼容,

2、不能把double类型的指针转换为float类型的指针,至少要避免不明智的类型转换。

3;指针和整数相加,在不超出数组的定义范围,p+1=&p[1]

4;指针求差,可求出两个元素之间的距离,差值的单位与数组类型的单位相同。

5;千万不要解引用未初始化的指针,可能会将有用的数据擦写掉,引起程序崩溃

保护数组中的元素:

函数中,当需要传递数组时,尽量传递指针,否则会浪费存储空 间,但传指意味着,原来的指针可能会被修改,可以在形参之前加const关键字。如果想修改数组内容,则不需要添加const。不可以把const数据的地址赋值给普通指针,否则,通过指针就可以修改const数组中的数据。C语言规定,使用非const标识符修改const数据导致的结果是未定义的。

如:const int * const p = arr;

前一个const限制了(*p)无法改变

后一个const限制了p的内容无法改变,即p的指向不能变。

指针和多维数组关系:

举例:Int arr[4][2];

1;arr 是该数组首元素地址,该数组首元素为一个含有两个int数据的数组,所以,arr 是这个含有两个数据的数组的地址

2;arr 为首元素地址,则arr = &arr[0];其中arr[0] = &arr[0][0]简而言之,arr[0]是占用一个int大小的数据的地址,arr是占用两个int大小的数据的地址,由于,都始于同一个地址故arr = arr[0];

3;当给指针加1时,arr+1,与arr[0]+1不同,一个加了两个Int大小,一个加了一个int大小。

4;解引用时,*(arr[0])= arr[0][0];*arr = arr[0]; 但是arr[0]是int类型的指针,该值地址是&arr[0][0],故*arr=&arr[0][0]简而言之,arr是地址的地址,必须解引用两次才能获得原始值,

指向多维数组的指针:

声明:int (* p)[2] //p指向一个内含两个int类型值的数组必须加括号否则就变成int * p[2],这说明p是一个内含两个指针元素的数组,每个元素都是指向int的指针。因为[]的优先级高于*

函数和多维数组:

声明函数:void fun(int(*p)[4]);当p当且仅当是一个函数的形式参数时,也可以这样

Void fun(int p[][4]);第一个方括号为空,表明p是一个指针。第二个方括号不能为空,由于编译器处理数组会转换成指针处理,当进行Arr+1的操作时,编译器不知道要在地址上加多少。

变长数组声明:

int quarters = 4;

int regions = 5;

double sales[regions][quarters]; // 一个变长数组

变长数组必须是自动存储类型,这表明无论在函数中声明还是作为函数形参声明,都不能使用static和extern存储类别说明符,变长数组中的“变”不是指可以修改一创建数组的大 小,而是指在创建数组时,可以使用变量指定数组的维度。

声明一个带二维变长数组参数的函数:

int sum2(int rows, int cols, int arr[rows][cols]);正确

int sum2(int arr[rows][cols], int rows, int cols);错误

因为arr的声明要使用两个参数,所以这两个参数必须要放 在数组参数的前面。

CH12—存储类别、链接和内存管理

12.1.1 作用域

1作用域描述程序中可访问标识符的区域。一个C变量的作用域可以是块作用域、函数作用域、函数原型作用域或文件作用域。

2块是用一对花括号括起来的代码区域。的局部变量(包括函数的形式参数)都具有块作用域。

3 函数作用域(function scope)仅用于goto语句的标签。

4 函数原型作用域(function prototype scope)用于函数原型中的形参名。函数原型作用域的范围是从形参定义处到原型声明结束。意味着编译器只关心类型,对形参名通常无关紧要。但是在变长数组中,形参名才有用

void fun(int n, int m, arr[n][m]);

方括号中必须使用在函数原型中已声明的名称。

5 文件作用域;变量的定义在函数的外面,就具有文件作用域。具有文件作用域的变量,从它的定义处到该定义所在文件的末尾均可见。文件作用域变量也称为全局变量。

12.1.2 链接

C变量3种链接属性:

外部链接、内部链接、无链接

无链接变量包含块作用域、函数作用域、函数原型作用域。外部链接变量可以在多文件程序中使用。可称为全局作用域或程序作用域内部链接变量只能在一个翻译单元中使用。简称文件作用域。

Int dog = 5 //文件作用域,外部链接

Static int cat = 3; //文件作用域,内部链接

12.1.13 存储期

C对象有4种存储期:

静态存储期、线程存储期、自动存储期、动态分配存储期

静态存储期:程序的执行期间一直存在,文件作用域具有静态存储期。

线性存储期:用于并发程序设计,程序执行可以被分为多个线程,具有线程存储期的对象,从被声明时到线程结束时一直存在。

自动存储期:块作用域的变量通常都具有自动存储期。当程序进入定义这些变量的时,为这些变量分配内存;当退出这个块时,释放刚才变量分配的内存,这种做法相对于把自动变量占用的内存视为一个可重复使用的工作区或暂存区。变长数组稍有不同,它的存储期从声明处到块的结尾,而不是从块的开始到块的结束。块作用域变量也能具有静态存储期,需要把变量声明在块中,而且要在声明前加上关键字static。

12.1.4—自动变量

1 属于自动存储类别的变量具有自动存储期、块作用域、无链接

2 默认情况下,声明在块或函数头中的任何变量都属于自动存储类别.

3 块作用域和无链接意味着只有变量定义所在的块中才能通过变量名访问该变量,另一个函数可以使用相同的变量名,但是该变量名是存储在不同内存位置上的另一个变量。

4 如果内层块的声明的变量与外层块中的变量同名,则内层块会隐藏外层块的定义,当离开内层块时,外层块的作用域又回到了原来的作用域。

12.1.5 寄存器变量

变量通常存储在计算机内存中,寄存器变量存储在CPU的寄存器中或者概括的说,存储在最快的可用内存中,与普通变量相比,访问和处理这些变量的速度更快,由于寄存器变量存储在寄存器而非内存中,所以无法获取寄存器变量的地址。绝大多数方面,寄存器变量和自动变量都一样,都是块作用域、无链接和自动存储期。使用类别说明符 register 便可声明寄存器变量。但是最快可用内存不够时,编译器会忽略你的请求,这种情况下,寄存器变量就变成普通的自动变量,即使这样,任然不可以对该变量使用地址运算符。

12.1.6 块作用域的静态变量

静态变量:该变量在内存中原地不动,并不是说它的值不可变。具有文件作用域的变量自动具有静态存储期。 可以创建具有静态存储期、块作用域的局部变量,但是程序 离开所在的函数后,这些变量不会消失,计算机在多次函数调用之间记录它的值。

注意:不可以在函数的形参中使用static

int wontwork(static int flu); // 不允许

12.1.7 外部链接的静态变量

外部链接的静态变量具有文件作用域、外部链接和静态存储期。把变量的定义声明放在所在函数的外面便创建了外部变量。可以在函数中添加关键字extern再次声明,如果一个源代码文件使用的外部变量定义在另一个源代码文件中,则必须用关键字extern在该文件中声明该变量。

1 初始化外部变量

如果未初始化外部变量,它们会自动被初始化为0;只能使用常量表达式初始化文件作用域变量;

比如:

size_t z = sizeof(int); //没问题,用于初始化的是常量表达式

只要不是变长数组,sizeof表达式可被视为常量表达式。

int x2 = 2 * x; // 不行,x是变量

2 使用外部变量

extern 告诉编译器,该函数中任何使用某一变量的地方都引用同一个定义在函数外部的量。

3 外部名称

4 定义和声明

不要用关键字extern 创建外部定义,只用它来引用现有的外部定义。外部变量只能初始化一次,且必须在定义该变量时进行。

比如:

// file_one.c

char permis = 'N';

...

// file_two.c

extern char permis = 'Y'; /* 错误 */

12.1.8—内部链接的静态变量

该存储类别的变量具有静态存储期、文件作用域、内部链接在所有函数外部,用存储类别说明符static定义的变量具有这种存储类别。

12.1.9 多文件

只有多个源文件,才能体现内部链接和外部链接的重要性。通常在一个文件中进行定义式声明(并初始化变量),然后在其 它文件中进行引用式声明来实现共享。

12.1.10 存储类别说明符

auto :表明变量是自动存储期,只能用于块作用域的变量声明中。由于在块中声明的变量本身就具有自动存储期,所以使用auto 主要是为了明确表达要使用与外部变量同名的局部变量的意图。

register :

只用于块作用域的变量,它把变量归为寄存器存储类别,请 求最快速度访问该变量。同时,还保护该变量的地址不被获取。

static :

创建的对象具有静态存储期,载入程序时创建对象,当 对象消失。如果static用于文件作用域声明,作用域受限于该文 件。如果 static 用于块作用域声明,作用域则受限于该块。因此,只要程序 在运行对象就存在并保留其值,但是只有在执行块内的代码时,才能通过标 887 识符访问。块作用域的静态变量无链接。文件作用域的静态变量具有内部链接。

extern :

表明声明的变量定义在别处,如果包含extern 的声明具有文件作用域,则引用的变量必须具有外部链接,如果包含Extern 的声明具有块作用域,则引用的变量可能具有外部链接或者内部链接。

12.1.11—存储类别和函数

函数存储类别:外部函数(默认)、静态函数、内联函数

举例:

double gamma(double); /* 该函数默认为外部函数 */

static double beta(int, int);

extern double delta(double, int);

同一程序中,其他文件中的函数可以调用gamma()、delta()不可以调用beta()。因为static 存储类别说明符创建的函数属于特定模块私有。通常的做法是:用 extern 关键字声明定义在其他文件中的函数。这样做 是为了表明当前文件中使用的函数被定义在别处。除非使用static关键字, 否则一般函数声明都默认为extern。

12.1.12—存储类别的选择

保护性程序设计的法则:

尽量在函数内部解决该函数的任务,只共享那些需要共享的变量

标签: #c语言连接器返回错误代码1是什么意思 #win10运行c语言