1. 指针的基本用法
是什么是指针?
- 指针是存储变量地址的变量。
- 可以通过指针访问和修改变量的值。
#include <stdio.h>
int main() {
// 定义一个整数变量
int num = 42;
// 定义一个指向整数的指针,并将其指向num的地址
int *ptr = #
// 输出变量的值和指针的值
printf("Value of num: %d\n", num);
printf("Value through pointer: %d\n", *ptr);
return 0;
}
在这个例子中,我们定义了一个整数变量 num,然后定义了一个指向整数的指针 ptr,并将其指向 num 的地址。通过 *ptr 可以访问指针指向的值。
其中,ptr放的是地址,*ptr则是访问指针指向的值
2. 指针和数组
指针与数组:
#include <stdio.h>
int main() {
// 定义一个整数数组
int numbers[] = {1, 2, 3, 4, 5};
// 定义一个指向整数的指针,并让它指向数组的第一个元素
int *ptr = numbers;
// 使用指针遍历数组并输出每个元素
for (int i = 0; i < 5; i++) {
printf("Element %d: %d\n", i, *(ptr + i));
}
return 0;
}
在这个例子中,我们定义了一个整数数组 numbers,然后定义了一个指向整数的指针 ptr,并让它指向数组的第一个元素。通过 *(ptr + i) 可以访问数组中的每个元素。
3. 指针和字符串
char *str = "Hello";
printf("String: %s\n", str);
注意,这里printf(“String: %s\n”, str);中的%s格式说明符表示要输出的是一个字符串,str是字符串的首地址。printf函数通过从str开始的地址开始读取字符,直到遇到空字符\0为止,然后输出这个字符串。
或者还可以如下输出:
#include <stdio.h>
int main() {
// 定义一个字符串
char str[] = "Hello, C!";
// 定义一个指向字符的指针,并让它指向字符串的第一个字符
char *ptr = str;
// 使用指针遍历字符串并输出每个字符
while (*ptr != '\0') {
printf("%c", *ptr);
ptr++;
}
return 0;
}
如果想要输出地址,可以使用%p格式说明符,如下:
printf("Address of the string: %p\n", (void *)str);
这样就会输出字符串的地址。 (void *)是为了避免编译器发出警告,因为%p要求传递一个void *类型的指针。
4. 指针和函数
① 指针作为函数参数
#include <stdio.h>
// 定义一个函数,接受两个整数和一个函数指针作为参数
int calculate(int a, int b, int (*operation)(int, int)) {
return operation(a, b);
}
// 定义一个函数,用于相加两个整数
int add(int a, int b) {
return a + b;
}
// 定义一个函数,用于相乘两个整数
int multiply(int a, int b) {
return a * b;
}
int main() {
// 使用指针作为函数参数进行加法运算
int resultAdd = calculate(3, 4, add);
printf("Addition Result: %d\n", resultAdd);
// 使用指针作为函数参数进行乘法运算
int resultMultiply = calculate(3, 4, multiply);
printf("Multiplication Result: %d\n", resultMultiply);
return 0;
}
在这个例子中,我们定义了一个函数 calculate,该函数接受两个整数和一个函数指针作为参数,用于执行相应的操作。然后,我们定义了两个函数 add 和 multiply,它们分别执行加法和乘法运算。最后,我们通过调用 calculate 函数,并传递相应的函数指针,实现了加法和乘法运算。
这些例子展示了在 C 语言中如何使用指针与函数相关联,无论是通过函数指针还是将指针作为函数参数传递。这种灵活性使得可以在运行时决定调用哪个函数,增强了代码的可扩展性和可维护性。
② 函数指针
函数指针是指向函数的指针变量。在C语言中,函数被存储在内存中的某个地址,而函数指针就是用来存储这个地址的变量。
函数指针的声明形式如下:
return_type (*pointer_name)(parameter_types);
其中:
return_type 是函数返回值的类型。
pointer_name 是函数指针的名字。
parameter_types 是函数的参数类型。
例如,以下是一个简单的例子:
#include <stdio.h>
// 定义一个函数
int add(int a, int b) {
return a + b;
}
int main() {
// 定义一个函数指针类型,该类型指向返回类型为int,参数为两个int的函数
typedef int (*SumFunction)(int, int);
// 声明一个函数指针变量,并让它指向add函数
SumFunction sumPtr = add;
// 使用函数指针调用函数
int result = sumPtr(3, 4);
printf("Result: %d\n", result);
return 0;
}
此外,在C语言中,函数名通常被解释为指向函数的指针。因此,在给函数指针赋值时,& 操作符通常是可选的,因为函数名本身就是一个指针。因此,SumFunction sumPtr = &add; 和 SumFunction sumPtr = add; 是等价的。
另外一个例子:
int add(int a, int b) {
return a + b;
}
int (*sumPtr)(int, int) = add;
int result = sumPtr(3, 4);
5. 常量指针和指向常量的指针有什么区别?
① 指向常量的指针
// 常量指针
const int *ptr1;
int const *ptr2;
表示指针 ptr 指向的整数是常量,即不能通过 ptr 修改所指向的整数的值。但是,ptr 本身是可以改变的,可以指向其他整数。这种情况下,被指向的整数是只读的。
int x = 10;
const int* ptr = &x;
*ptr = 20; // 这是非法的,因为 ptr 指向的整数是常量
ptr = &y; // 这是合法的,ptr 本身是可以改变的
② 常量指针
int* const ptr
这表示指针 ptr 本身是常量,即不能通过 ptr 修改指针的值(不能让 ptr 指向其他地方)。但是,可以通过 ptr 修改所指向的整数的值。
int x = 10;
int y = 20;
int* const ptr = &x;
*ptr = 30; // 这是合法的,通过 ptr 修改了所指向的整数的值
ptr = &y; // 这是非法的,因为 ptr 本身是常量,不能指向其他地方
总结起来:
const int* ptr:指向常量的指针,所指向的值是只读的。
int* const ptr:常量指针,指针本身是只读的,但所指向的值可以修改。
此外,在C和C++中,int *p
和 int* p
实际上是相同的,它们都表示 p 是一个指向整数的指针。这是因为在声明指针时,* 既可以放在类型名前,也可以放在变量名后。这两者的语法是等效的,两者都被广泛使用。