笔记_C语言_指针与数组

指针与地址

一元运算符&可用于取一个对象的地址,因此,下列语句:
p = &c;
将把 c 的地址赋值给变量 p,我们称 p 为“指向”c 的指针。地址运算符&只能应用于内存中 的对象,即变量与数组元素。它不能作用于表达式、常量或 register 类型的变量。
一元运算符*是间接寻址或间接引用运算符。当它作用于指针时,将访问指针所指向的对象。

指针与函数参数

由于 C 语言是以传值的方式将参数值传递给被调用函数。因此,被调用函数不能直接修改主调函数中变最的值。

#include <stdlib.h> 
#include <stdio.h>
void main() {
 //void swap(int x, int y);
 int a = 1, b = 2;
 void swap(a, b);
 printf("%d,%d\n",a,b);
 swap(&a,&b);
 printf("%d,%d\n", a, b);
 system("pause");
}
void swap(int *x, int *y)  /* WRONG */
{
 int temp;
 temp = *x;
 *x = *y;
 *y = temp;
}

输出的结果为:

1,2
2,1
请按任意键继续. . .

指针与数组

#include<stdio.h>
#include<stdlib.h>
void main() {
 int a[10] = { 0,1,2,3,4,5,6,7,8,9, };
 int *pa,x;
 //pa = &a[0];
 pa = a;//因为a表示数组中的第一位,所以这句话和pa = &a[0];是一样的意思
 x = *pa;
 printf("%d\n",x);
 //x = *(pa+1);//指针加一,在数组中对应的位置也加一
 x = pa[1];//指针也可以加下标,所以这句话和x = *(pa+1);是一样的
 printf("%d\n", x);
 pa = a + 2;//&a[2]和a+2的含义是一样的
 x = *pa;
 printf("%d\n",x);
 printf("%d\n", *(pa+1));//也可以在指针后面直接加偏移量来引用数组
 system("pause");
}

但是,我们必须记住,数组名和指针之间有一个不同之处,指针是一个变量,因此,在 C 语言中,语句 pa=a 和 pa++都是合法的。但数组名不是变量,因此,类似于 a=pa 和 a++形 式的语句是非法的。
当把数组名传递给一个函数时,实际上传递的是该数组第一个元索的地址。在被调用函 数中,该参数是一个局部变量,因此,数组名参数必须是一个指针,也就是一个存储地址值 的变量。

地址算术运算

首先,在某些情况下对指针可以进 行比较运算。例如,如果指针 p 和 q 指向同一个数组的成员,那么它们之间就可以进行类似 于==、!=、<、>=的关系比较运算。如果 p 指向的数组元素的位置在 q 指向的数组元素位置 之前,那么关系表达式
p < q
的值为真。任何指针与 0 进行相等或不等的比较运算都有意义。但是,指向不同数组的元素 的指针之间的算术或比较运算没有定义。 (这里有一个特例:指针的算术运算中可使用数组最 后一个元素的下一个元素的地址。)
其次。我们从前面可以看到,指针可以和整数进行相加或相减运算。例如,结构
p + n
表示指针 p 当前指向的对象之后第 n 个对象的地址。无论指针 p 指向的对象是何种类型,上 述结论都成立。在计算 p+n 时,n 将根据 p 指向的对象的长度按比例缩放,而 p 指向的对象 的长度则取决于 p 的声明。例如,如果 int 类型占 4 个字节的存储空间,那么在 int 类型的 计算中,对应的 n 将按 4 的倍数来计算。
指针的减法运算也是有意义的:如果 p 和 q 指向相同数组中的元索,且 p<q,那么 q-p+1 就是位于 p 和 q 指向的元索之间的元素的数目

字符指针与函数

C 语言没有提供将整个字符串作为一个整体进行处理的运算符。
下面两个定义之间有很大的差别:

char amessage[] = "nw is the time";//定义一个数组
char *pmessage = "now is the time";//定义一个指针 

上述声明中,amessage 是一个仅仅足以存放初始化字符串以及空字符’\0’的一维数组。数 组中的单个字符可以进行修改, 但amessage始终指向同一个存储位置。另一方面,pmessage 是一个指针,其初值指向一个字符串常量,之后它可以被修改以指向其它地址,但如果试图 修改字符串的内容,结果是没有定义的。
在读取指针 p 指向的字符之前先对 p 执行自减运算。事实上,下面的两个表达式:

*p++ = val;//将 val 压入栈
val = *--p;//将栈顶元素弹出到 val 中

是进栈和出栈的标准用法。

指针数组以及指向指针的指针

指针数组的数组变量也是可以改变值的

多维数组

#include<stdio.h>
#include<stdlib.h>
void main() {
 static char daytab[2][13] = { { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } };
 int year; int month; int day;
 int i, leap;
 scanf("%d,%d,%d",&year,&month,&day);
 leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
 for (i = 1; i < month; i++)
  day += daytab[leap][i];
 printf("%d",day);
 system("pause");
}

如果将二维数组作为参数传递给函数,那么在函数的参数声明中必须指明数组的列数。 数组的行数没有太大关系,因为前面已经讲过,函数调用时传递的是一个指针,它指向由行 向量构成的一维数组,其中每个行向量是具有 13 个整型元素的一维数组
考虑这样一个问题:编写一个函数 month_name(n),它返回一个指向第 n 个月名字的 字符串的指针。这是内部 static 类型数组的一种理想的应用。month_name 函数中包含一 个私有的字符串数组,当它被调用时,返回一个指向正确元素的指针。本节将说明如何初始 化该名字数组。
指针数组的初始化语法和前面所讲的其它类型对象的初始化语法类似:

char *month_name(int n)    {
        static char *name[] = {
                    "Illegal month",
                    "January", "February", "March",
                    "April", "May", "June",
                    "July", "August", "September",
                    "October", "November",
                      "December"
                                }; 

其中,name 的声明与排序例子中 lineptr 的声明相同,是一个一维数组,数组的元素为字 符指针。name 数组的初始化通过一个字符串列表实现,列表中的每个字符串赋值给数组相应 位置的元素。第 i 个字符串的所有字符存储在存储器中的某个位置,指向它的指针存储在 name[i]中。由于上述声明中没有指明 name 的长度,因此,编译器编译时将对初值个数进 行统计,并将这一准确数字填入数组的长度。 # 指针数组的初始化

指针与多维数组

对于 C 语言的初学者来说,很容易混淆二维数组与指针数组之间的区别

命令行参数

指向函数的指针

复杂声明

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值