C语言基础
2021-09-26
变量和初始化 #
外部变量 #
- 外部变量和函数具有如下性质:通过同一个名字引用的所有外部变量实际上都是引用同一个对象。
- 如果外部变量的定义和变量的使用不在同一个文件中,需要在相应的变量声明中强制性的使用关键字extern。
- 变量的声明用于说明变量的属性(主要是变量的类型),而变量的定义除此外还将引起存储器的分配。以下语句如果放在所有函数的外部,那么这两条语句将定义外部变量sp和val,并为其分配存储单元。
int sp;
//声明外部变量必须指定数组长度。
double val[100];
- 下面这两行声明了两个外部变量,并没有建立变量或分配存储空间。
extern int sp;
extern double val[];
静态变量 #
- 用static声明限定
外部变量和函数
,可以将其声明后的对象的作用域限定为被编译源文件的剩余部分,通过static限定外部对象,可以隐藏外部对象
。 - 通常情况下,函数名是全局可访问的,对于整个程序各个部分而言都可见。但如果将函数声明为static类型,则该函数除了对该函数声明所在的文件可见外,其他文件都无法访问。
- static也可用于声明内部变量,但是不管函数是否被调用,它一直存在。static类型的内部变量是一种只能在某个特定函数中使用但是一直占用存储空间的变量。
初始化 #
- 在不进行显式初始化的情况下,
外部变量和静态变量都将被初始化为0
,而内部变量和寄存器变量的初值则没有定义。 - 对于外部变量和静态变量来说,初始化变量表达式必须是常量表达式,且只初始化一次。
- 数组的初始化实在声明后紧跟一个初始化列表。
//当省略数组的长度时,编译器将把花括号中的长度作为数组的长度
int days[] = {31, 28, 31,30};
//字符数组的初始化方式如下
char pattern[] = "oule";
//等价于
char pattern = {'o', 'u', 'l', 'e', '\0'};
运算 #
- 计算char类型或short类型时,会将其转化为int类型来计算。
预处理器 #
#include
将指定文件的内容包含到当前文件中。#define 名字 替换文本
将名字
替换为替换文本
。sizeof
可以用来计算任一对象的长度,如sizeof(int)
。- 条件包括
#if SYSTEM == SYSV
#define HDR "sysv.h"
#elif SYSTEM == BSD
#define HDR "bsd.h"
#else
#define HDR "default.h"
#endif
#include HDR
#ifdef HDR
printf("DEF HDR");
#endif
指针与数组 #
&
表示取一个对象的地址
//把c的地址给p
p = &c
*
作用于指针时,将访问指针所指向的对象。- 指针只能指向某种特定类型的对象(void*除外)。
- 通过数组下表能实现的操作都可以通过指针来实现。
int a[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
//将指针pa指向数组的第0个元素,pa的值为a[0]的地址
//等价于pa = a;
int *pa = &a[0];
//*pa 和 a[0] 的含义是相同的
int x1 = *pa;
printf("x1 的值为 %d\n", x1);
//&a[1] 和 a + 1 的含义是相同的
int x2 = *(a + 1);
printf("x2 的值为 %d\n", x2);
//pa[2] 和 *pa[2] 的含义是相同的
int x3 = pa[2];
printf("x3 的值为 %d\n", x3);
-
数组和指针的不同点
- 指针是一个变量,所以
pa = a
和pa++
都是合法的。 - 数组名不是变量,
a = pa
和a++
非法。
- 指针是一个变量,所以
-
在函数的定义中,以下两种形参是等价的:
char s[];
char *s;
- 可以将数组的一部分传递给函数:
//将起始于a[2]的子数组的地址传递给函数f
f(&a[2]);
//或
f(a + 2);
字符指针 #
-
字符串常量是一个字符数组,在字符串的内部表示中,字符数组以空字符
\0
结尾。 -
下面两个定义之间有很大的差别:
//定义了一个指针,指向了一个字符串常量,不能修改字符串的值
char *pmessage = "now is the time";
//定义了一个数组,数组中的单个字符可以修改
char a[] = "now is the time";
二维数组和指针数组 #
//真正的二维数组,分配了200个int类型长度的存储空间
int a[10][20];
//仅分配了10个指针,并没有对指针进行初始化,需要显式的进行初始化
//b的每个元素都是int *类型的指针,b并非是二维数组
int *b[10];
//例:
int *b[10];
int x1 = 1;
b[0] = &x1;
int x2[] = {21, 22};
b[1] = x2;
//相当于是一维数组,数组中的每个元素是字符串指针
char *name[] = {"illegal month", "jan", "feb", "mar"};
//二维数组,数组中的每个元素的长度是15,不够补充\0
char aname[][15] = {"illegal month", "jan", "feb", "mar"};
结构 #
//声明方式
struct point {
int x;
int y;
};
void print1(struct point *pt);
int main()
{
struct point pt;
pt.x = 1;
pt.y = 2;
print1(&pt);
}
void print1(struct point *pt)
{
//pt->x 等价于 (*pt).x
printf("x is %d\ny is %d\n", pt->x, pt->y);
}
类型定义typedef #
- typedef用来建立新的数据类型名。
//类型定义
typedef int Length;
//声明变量
Length len, maxlen;
typedef struct point {
int x;
int y;
} Pointx;
Pointx px;
union #
- 一个变量可以合法的保存多种数据类型中的任何一种类型的对象。
union u_tag {
int ival;
float fval;
char *swal;
}u;