MST
星途 面试题库

面试题:C语言中指针与数组的关系及差异

请阐述C语言中指针和数组之间的关系,并且举例说明它们在使用上有哪些关键差异。例如,对于一个字符数组和指向字符的指针,在初始化、访问元素、传递给函数等方面有何不同?
31.0万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

指针和数组的关系

  1. 本质区别:数组是一块连续的内存空间,用于存储相同类型的数据。而指针是一个变量,它存储的是另一个变量的内存地址。
  2. 联系:在很多情况下,数组名可以被当作指针来使用。比如在表达式中,数组名会自动转换为指向数组首元素的指针。例如,对于数组 int arr[5];arr 就相当于 &arr[0],即指向数组首元素的指针。

关键差异举例(以字符数组和指向字符的指针为例)

  1. 初始化
    • 字符数组: 可以通过多种方式初始化。例如:
char str1[] = "hello";
char str2[6] = {'h', 'e', 'l', 'l', 'o', '\0'};

这里 str1 是一个字符数组,编译器会根据初始化内容自动确定数组大小为 6(包括字符串结束符 '\0')。str2 明确指定了数组大小为 6,并逐个字符初始化。 - 指向字符的指针

char *ptr = "world";

这里 ptr 是一个指向字符串常量 "world" 的指针。注意,字符串常量存储在只读内存区域。也可以先定义指针,再赋值:

char *ptr;
ptr = "world";
  1. 访问元素
    • 字符数组: 通过下标方式访问数组元素。例如:
char str[] = "hello";
printf("%c\n", str[2]); // 输出 'l'
- **指向字符的指针**:

既可以通过下标方式(因为指针可以像数组名一样使用),也可以通过解引用指针并移动指针位置的方式访问。例如:

char *ptr = "hello";
printf("%c\n", ptr[2]); // 输出 'l'
printf("%c\n", *(ptr + 2)); // 同样输出 'l'
  1. 传递给函数
    • 字符数组: 当将字符数组传递给函数时,实际上传递的是数组首元素的地址,即一个指针。函数可以通过这个指针访问数组中的所有元素。例如:
void printArray(char arr[]) {
    int i = 0;
    while (arr[i] != '\0') {
        printf("%c", arr[i]);
        i++;
    }
}
int main() {
    char str[] = "hello";
    printArray(str);
    return 0;
}

这里 printArray 函数的参数 arr 本质上是一个指针,尽管声明看起来像数组。 - 指向字符的指针: 传递指向字符的指针给函数与传递数组名类似,因为数组名在传递时会转换为指针。例如:

void printPtr(char *ptr) {
    while (*ptr != '\0') {
        printf("%c", *ptr);
        ptr++;
    }
}
int main() {
    char *str = "hello";
    printPtr(str);
    return 0;
}

这里 printPtr 函数接收一个指向字符的指针,并通过解引用和移动指针来访问字符串中的字符。

  1. 内存分配和可修改性
    • 字符数组: 数组的内存是在栈上分配(如果是局部数组),并且数组中的内容可以修改(除非数组被声明为 const)。例如:
char str[] = "hello";
str[0] = 'H'; // 合法,将 'h' 修改为 'H'
- **指向字符的指针**:

如果指针指向的是字符串常量,如 char *ptr = "world";,则不能通过指针修改字符串内容,因为字符串常量存储在只读内存区域。如果指针指向的是动态分配的内存(如 char *ptr = (char*)malloc(10);),则可以修改。例如:

char *ptr = "world";
// ptr[0] = 'W'; // 不合法,试图修改只读内存
char *ptr2 = (char*)malloc(10);
strcpy(ptr2, "hello");
ptr2[0] = 'H'; // 合法,修改动态分配内存中的内容
free(ptr2);