C programing language

指针与数组

指针与地址

通常的机器有一系列连续的编号或编址的存储单元,它们可以以连续的方式存放不同数据类型的数据。如4个相邻的字节存放一个long类型变量,单个字节存储char类型变量。

一元运算符&可用于取一个地址。
P = &c;
将c的地址复制给变量P,我们称P为指向c的指针。地址运算符&只能应用于内存中的对象,即变量和数组。 他不能作用于表达式,常量或寄存器变量。
一元运算符*是间接寻址或间接引用的运算符。当它作用于指针时,将访问指针所指向的对象。

int x = 1, y = 2, z[10];
int *ip;	//声明ip为int类型的指针
ip = &x;	//ip指向x
y = *ip;	//y == 1
*ip = 0;	//x为0
ip = &z[0];	//指向z[0]

指针只能指向某种特定类型的变量,每个指针都必须指向某种特定的数据类型。(EXCEPTION:void类型的指针可以存放指向任何数据类型的指针,但是不能间接引用自身。)
一元运算符的*和&的优先级高于算术运算符,*ip += 1等同于 ++*p等同于(*ip)++。

指针和函数

指针参数使得被调用的函数可以访问和修改主调函数中对象的值。除了经典的swap例子外,还有:
函数getline接受自由格式的输入,并且执行转换,输入的字符分解成整数,每次调用获得一个整数。getint需要返回转换后得到的整数,在到达输入结尾时要返回文件结束标记。
scanf的设计方法:将标识是否到达文件结尾状态作为getint的返回值,使用一个指针参数储存转换后的整数并传回主调函数。

int n, array[SIZE], getint(int *);
for (n = 0; n < SIZE && getint(&array[n]) != EOF; n++)
;

此getint函数在到达文件末尾是返回EOF,当下一个输入不是数字时返回0,当输入中包含一个有意义的数字时返回一个正值。

#include <ctype.h>

int getch(void);
void ungetch(int);
//输入中的下一个整数赋值给*pn
int getint(int *pn){
	int c, sign;
	while (isspace(c = getch()))	//跳过空白符
		;
	if(!isdigit(c) && c != EOF && c != '+' && 'c' != '-') {
		ungetch(c);	//输入不是数字
		return 0;
	}
	sign = (c == '-') ? -1 : 1;
	if (c == '+' || c == '-')
		c = getch();
	for (*pn = 0; isdigit(c); c = getch())
		*pn = 10 * *pn + (c - '0');
	*pn *= sign;
	if (c != EOF)
		ungetch(c);
	return c;
}

*getchar(), getc(), getch(), getche()
The difference between getc() and getchar() is getc() can read from any input stream, but getchar() reads from standard input. So getchar() is equivalent to getc(stdin).

getch() is a nonstandard function and is present in conio.h header file which is mostly used by MS-DOS compilers like Turbo C. It is not part of the C standard library or ISO C, nor is it defined by POSIX (Source: http://en.wikipedia.org/wiki/Conio.h)
Like above functions, it reads also a single character from keyboard. But it does not use any buffer, so the entered character is immediately returned without waiting for the enter key.
getche() like getch(), this is also a non-standard function present in conio.h. It reads a single character from the keyboard and displays immediately on output screen without waiting for enter key.

数组和指针

数组下标能完成的事情都可以通过指针来实现,执行速度也更快。

int *pa, a[10];
pa = &a[0];

*(pa + 1)指向a[1], (pa + i)指向a[i]。然而在计算数组元素a[i]时C语言会先把其转化成(a+i)的形式,然后再进行求值。
同理,加上取址运算符,&a[i]和a+i的含义也是相同的。
把数组名传递进一个函数时,实际上传递的是该数组的第一个元素的地址。在被调用函数中,该参数是一个局部变量,因此,数组名必须是一个指针,也就是一个存储地址值的变量。
例如,编写strlen函数:

int strlen(char *s){
	int n;
	for (n = 0; *s != '\0';  s++)
		n++;
	return n;
}

在函数定义中,形式参数(formal parameters)
char []char *s 是等价的。我们更习惯于最后一种方式,比前者更直观的表明了参数是一个指针。如果将函数名传递给函数,函数可以根据情况判断是按照数组还是指针处理,随后根据相应方式操作该参数。
也可以把指向子数组的起始位置的指针传递给函数,这样就将数组的一部分传递给了函数。例如,如果a是一个数组,那么下面两个函数调用f(&[2])与f(a+2)都将把起始于2的子数组地址传递给函数f。在函数f中,参数的声明可以是f(array[])和f(*array)。

有效的指针变量的运算包括:

  1. 相同类型的指针之间的赋值运算
  2. 指针同整数之间的加法运算或减法运算
  3. 指向相同数组中元素两个指针的比较运算
  4. 指针赋值为0或指针与0之间的比较运算
    其他的运算都是非法的。

字符指针

字符串常量是一个字符数组。字符串出现在程序中时,一般是通过字符指针访问该字符串的。字符串可以通过指向第一个元素的指针访问。
除了作为函数参数之外,字符串常量还有其他用法。

char *s
s = " hello world! "

指向该字符数组的指针被赋值给s,该过程并没有字符串的赋值,而只是涉及到指针的操作。因此,以下两个定义有很大差别:

char s1[] = "hello world!"
char *s2 = "hello world!"

第一个是仅足以存放字符串以及空字符的一维数组。数组中的单个字符可以修改,但是s1始终指向同一个储存位置。而s2可以指向其他地址,如果试图修改字符串的内容,结果是没有定义的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值