Post

指针数组与数组指针

指针数组与数组指针

1.指针数组

指针数组可以说成是”指针的数组”,首先这个变量是一个数组,其次,数组的所有元素都是指针类型,在32位系统中,指针占四个字节。

1
2
char* arr[4] = {"hello", "world", "zhejiang", "hangzhou"};
//arr就是我定义的一个指针数组,它有四个元素,每个元素是一个char *类型的指针,这些指针存放着其对应字符串的首地址。

这就相当与定义char *p1 = “hello”,char *p1 = “world”,char *p3 = “zhejiang”, char *p4 = “hangzhou”,这是四个指针,每个指针存放一个字符串首地址,然后用arr[4]这个数组分别存放这四个指针,就形成了指针数组。

2.数组指针

首先定义一个数组指针:

1
char (*ptr)[4];

ptr是一个指针,指向char [4]的数组。注意这个写法,容易误导。

3.示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void func() {
    // 1.
    int arr[4] = {0, 1, 2, 3};
    printf("arr: %p\n", arr);
    printf("arr_value: %d\n", *arr);
    // 2.
    int* p1 = arr;
    printf("p1: %p\n", p1);
    printf("p1_value: %d\n", *p1);
    // 3.
    int (*p2)[4] = &arr;  // 注意这里不能写成int (*p2)[4] = arr
    printf("p2: %p\n", p2);
    printf("p2_value: %d\n", *p2[0]);
}

输出结果为:

1
2
3
4
5
6
arr: 0x7ffe60abb160
arr_value: 0
p1: 0x7ffe60abb160
p1_value: 0
p2: 0x7ffe60abb160
p2_value: 0

为什么2可以直接赋值,而3需要取址,原因是作为指针,p1与p2指向的对象不同,即指针类型不同,前者指向int类型,后者指向int [4]类型,因此作为数组首地址的arr可以直接赋值给p1,但是需要取地址后赋值给p2

4.字符数组与字符串

正好一并记录一下字符串与数组

4.1 定义

字符数组:元素类型为字符型的数组。

1
char ch[5] = {'a', 'b', 'c', 'd', 'e'};

字符串:用一对双引号括起来的若干个字符序列。

1
char* str = "abcde";

字符串的存储形式与字符数组的存储形式是一样的,除了以下两点区别:

  1. 字符串本身存储在程序的只读存储区(非常低的一段地址空间)
  2. 字符串除了所有可见的字符外,末尾还有一个’\0’(ASCII码值为0),作为字符串结束的标志。

4.2 内存图

1520295705884

字符串是存储在数据段的只读数据,只可访问,不可修改,所以像char *str="abcde";这样定义的字符串又叫做字符串常量。

访问字符串时需要知道字符串的首地址,可以把字符串的首地址保存到一个字符指针里面,这样,就可以通过这个字符指针访问字符串了,如下所示:

1
2
3
4
char *str = "abcde";
printf("%s\n", str);    //打印整个字符串常量
printf("%c\n", *str);   //打印字符串常量的第一个字符
printf("%c\n", str[1]); //打印字符串常量的第二个字符

字符串常量存储的值不可改变,像下面这样的操作会引起程序崩溃:

1
*(str + 2) = 'g';   //错误,字符串里面的值不可以修改

因为字符串的存储形式与字符数组一致,所以可以用字符串对字符数组进行初始化,如下:

1
2
char ch[] = "abcde";
char ch[] = { "abcde" };

与之等价的写法为:

1
2
char ch[6] = {'a', 'b', 'c', 'd', 'e', '\0'};
char ch[] = {'a', 'b', 'c', 'd', 'e', '\0'};

需要注意的是:

char ch[5] = "abcde";会报错,越界了,必须为最后一位\0留一个位置,需要写成char ch[6] = "abcde";

但是写成char ch[5] = {'a', 'b', 'c', 'd', 'e'};就不会有问题

This post is licensed under CC BY 4.0 by the author.