写一个简单的例子,了解编译预处理。
#include "stdio.h" //“#include <stdio.h>” 的另一种写法
#define N 10 //宏定义
#define M 10*N
#define S(r) 3.14*a*a
int main() {
int a = 23;
#ifdef N
printf("N已宏定义\n");
#else
printf("N尚未宏定义\n");
#endif
#ifndef M
printf("M尚未宏定义\n");
#else
printf("M已宏定义\n");
#endif
#if None //输出为假
printf("真!\n");
#else
printf("假!\n");
#endif
printf("N=%d\nM=%d\nS(r)=%.2f", N, M, S(a));
return 0;
}
输出结果。
数据访问的两种方式:直接访问和间接访问。
实际应用中,把一个变量在内存中的起始地址简称为该变量的地址。
由于通过地址可以找到变量的内存单元,可以说,地址指向该变量单元,因此C语言把地址形象化的称为指针。
指针变量的值是地址。
写一个简单的例子。
#include "stdio.h"
int main() {
int *p,a; //定义指针 p 和变量 a
a = 10;
p = &a; //将变量 a 的地址赋给 p
printf("输出变量a的地址:%x\n使用指针间接输出变量a的值:%d", p, *p);
//注意看,p和*p
return 0;
}
输出结果。
存放地址的变量是一种特殊的变量,它只能用来存放地址而不能用来存放其他类型(如整型、实型、字符型)的数据,需要专门加以定义。
指针是专门用来存放地址的,必须定义为“指针类型”,定义指针变量的一般形式如下:
类型说明符 *指针变量名
类型说明符是指指针变量所指向的变量的数据类型,称为指针的基变量,即指针的指向类型。
取地址运算符&的功能是取出运算对象的地址,其结果是返回得到对象的指针(或地址)。
取地址运算符&可以将变量、数组元素、结构体变量或成员的地址作为运算结果返回,不能用于常数、表达式,如:&i、&a[i]、&s.k是合法的,&100、&(i+4)是不合法的。
不要将一个整数赋值给指针变量,除整数0以外。系统无法识别数值对应的内存单元中存放的是什么类型。
指针运算符 * 用于一个地址(例如指针变量)之前,表示取 * 号后指针变量指向内存单元中的内容。
运算符 & 和 * 都是单目运算符,优先级相同,具有右结合性,* 与 & 互为逆运算。如“&*p”,表示先找出p所指向的单元,再取出该单元的地址;“*&i”表示先取出变量i的地址,再取出该地址对应单元的内容。
零指针:指针变量除了可以初始化为一个地址值,也可以为零(0),这个指针称为零指针或空指针。零指针在程序中常作为状态比较。
void*指针:通用指针的类型用void*表示,因此也称为void指针或空类型指针,表示不指定指针变量是指向哪一种类型对象,当需要使用通用指针所指的数据参加运算时,要进行强制类型转换。
写一个简单的例子。
#include "stdio.h"
int main() {
char *pc, ch = 'a';
double r = 2.5, *pd = &r;
void *pv = 0; //通用指针
pv = &ch; //直接把任意变量的地址赋给通用指针
pc = (char *)pv; //强制类型转换,把通用指针的值赋给普通指针
printf("%c,%c\n", (*(char *)pv), *pc); //通用指针转换后可使用指针运算符
pv = pd; //不需要指针类型转换
printf("%1.2f", *(double *)pv);
return 0;
}
输出结果。
对于取地址运算符&的妙用,写一个例子。
#include "stdio.h"
void p(int x) {
x = 1024;
printf ("p函数里的值是%d\n", x);
}
void t(int &y) {
y = 1024;
printf ("t函数里的值是%d\n", y);
}
int main() {
int a = 1;
printf("原来的a是%d\n", a);
p(a);
printf("使用函数p后a变成了%d\n", a);
t(a);
printf("使用函数t后a变成了%d", a);
return 0;
}
输出结果。