C语言数组与指针

一维数组与指针

int a[10];
int *pa;

一维数组的数组名代表的就是该数组第一个元素的地址,所以复制语句pa=&a[0]等价于pa=a。对数组元素a[i]的引用等价于*(a+i)。在计算数组元素a[i]的值时,C语言实际上先将*(a+1)后再进行求值,所以用指针编写的程序比用数组下标编写的程序执行速度快。

数组名和指针之间有一个不同之处,指针是一个变量,pa=a和pa++都是合法的。但数组名不是变量,因此,类似于a=pa和a++形式的语句是非法的。

当把数组名传递给一个函数时,实际传递的是该数组第一个元素的地址。在被调用函数中,该参数是一个局部变量,因此,数组名参数必须是一个指针。

在函数定义中,形式参数char s[]和char *s是等价的。通常使用后一种形式,因为它比前者更直观地表明了该参数是一个指针。

字符数组和字符指针

char a[] = "Hello";
char *p = "Hello";

a是一个仅仅足以存放初始化字符串以及空字符’\0’的一维数组。数组中的单个字符可以进行修改,但a始终指向同一个存储位置。
p是一个指针,其初值指向一个字符串常量,之后它可以被修改以指向其他地址,但是不能修改字符串的内容。
char *p = “Hello”,”Hello”保存在静态数据区,该数据不能修改。由指针m指向,不能通过指针m来修改静态数据区的值。
char a[] = “Hello”,”Hello”保存在栈空间数组里。 数组名为a, 变量名为数组的首地址。可以通过a[i]=’a’或*(a+i)=’a’的形式来修改数组内容。
所以下面这个例子中,p1和p2地址相同,str1和str2地址不同

const char str1[] = "abc";
const char str2[] = "abc";
const char *p1 = "abc";
const char *p2 = "abc";

指针与多维数组

比较两个定义

int a[10][20];
int *b[10];

从语法角度讲,a[3][4]和b[3][4]都是对int对象的合法引用。但a是一个真正的二维数组,它分配了200个int类型长度的存储空间,并且通过常规的矩阵下标计算公式20*row+col计算得到元算a[row][col]的位置。
但是对b来说,该定义仅仅分配了10个指针,并且没有对它们初始化。假定b的每个元素都指向一个具有20个元素的数组,那么编译器就要为它分配200个int类型长度的存储空间以及10个指针的存储空间。

指针数组的优点

数组的每一行长度可以不同,b的每个元素不一定都指向一个具有20个元素的数组。

二维数组和二维指针

二维数组和二维指针的概念很容易混淆,请看下面这段代码。

#include <stdio.h>

void print_str(char** strs, int i)
{
    printf("strs[%d]=%s", i, strs[i]);
}

int main(int argc, char **argv)
{
    char strs[10][100] = {"Hello", "World"};
    print_str(strs, 0);

    return 0;
}

执行这段程序,会得出现Segmentation Fault。
Segmentation Fault是由于程序试图访问不该访问的内存,详细介绍见Wikipedia
https://en.wikipedia.org/wiki/Segmentation_fault

变量strs实际为一个类型为char (*)[100]的指针,指向二维数组的第一个元素,即一个包含100个char的数组,指针的值实际上也等于二位数组第一个char元素的地址。print_str函数的参数声明为char**,即二级指针,参数传递不会改变指针的值。所以strs的值跟main中定义的strs的值是一样的,不过print_str中的strs是二级指针。那么str[0]则是一级指针,strs[0]=*(strs+0),那么strs[0]的值为字符串“Hell”所占四个字节的值对应的地址,“Hell”对应的ASCII码为0x48 0x65 0x6C 0x6C, 组成的地址为0x6C6C6548(little endian),而此处内存禁止访问,所以出现了Segmentation Fualt。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值