前言
指针是C语言中一个强大且常见的概念,它允许我们直接操作内存中的数据,实现高效的数据处理与传递。虽然指针在C编程中扮演着重要角色,但它的概念可能对初学者来说有些抽象。
1.什么是指针?
在计算机科学中,指针是一个存储变量地址的变量。它允许我们直接访问内存中的数据,是C语言中重要的工具之一。
内存单元的编号 == 地址 == 指针
2. 指针的基础用法
指针允许我们直接访问内存中的数据。以下示例演示了如何声明、初始化和使用指针来访问变量的值。
int main() {
int num = 42;
int* ptr; // 声明一个整型指针变量
ptr = # // 将ptr指向num的地址
printf("num的值 %d\n", num);
printf("ptr的值: %p\n", ptr); // %p 用于打印指针的地址
printf("ptr指向的值: %d\n", *ptr); // *ptr 获取指针所指向的值
return 0;
}
2. 指针与数组
数组名本身就是一个指向数组首元素的指针。
这意味着,我们可以像操作指针一样操作数组,以及使用指针算术运算来遍历数组。
int arr[] = {1, 2, 3, 4, 5};
int *ptr = arr; // ptr指向数组的第一个元素
int firstElement = *ptr; // firstElement = 1
其实数组名就是数组⾸元素(第⼀个元素)的地址是对的,但是有两个例外:
• sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩, 单位是字节 •
&数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素 的地址是有区别的)
除此之外,任何地⽅使⽤数组名,数组名都表⽰⾸元素的地址
3.指针与函数
可以把一个指针声明成为一个指向函数的指针。
void test()
{
printf("hehe\n");
}
void (*pf1)() = &test;
void (*pf2)()= test;
int Add(int x, int y)
{
return x+y;
}
int(*pf3)(int, int) = Add;
int(*pf3)(int x, int y) = &Add;//x和y写上或者省略都是可以的
代码实例如下:
#include <stdio.h>
int add(int a, int b) {
return a + b;
}
int subtract(int a, int b) {
return a - b;
}
int main() {
int (*operation)(int, int); // 声明一个指向函数的指针
operation = add; // 将指针指向add函数
printf("Addition: %d\n", operation(5, 3));
operation = subtract; // 将指针指向subtract函数
printf("Subtraction: %d\n", operation(10, 4));
return 0;
}
4.指针和结构类型的关系
可以声明一个指向结构类型对象的指针。
struct MyStruct
{
int a;
int b;
int c;
};
struct MyStruct ss={20,30,40};
//声明了结构对象ss,并把ss 的成员初始化为20,30 和40。
struct MyStruct *ptr=&ss;
//声明了一个指向结构对象ss 的指针。它的类型是
//MyStruct *,它指向的类型是MyStruct。
int *pstr=(int*)&ss;
//声明了一个指向结构对象ss 的指针。但是pstr 和
//它被指向的类型ptr 是不同的。
5. 指针运算
指针的基本运算有三种,分别是:
• 指针± 整数
• 指针-指针
• 指针的关系运算
5.1指针± 整数
为数组在内存中是连续存放的,只要知道第⼀个元素的地址,顺藤摸⽠就能找到后⾯的所有元素。
#include <stdio.h>
//指针+- 整数
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int *p = &arr[0];
int i = 0;
int sz = sizeof(arr)/sizeof(arr[0]);
for(i=0; i<sz; i++)
{
printf("%d ", *(p+i));//p+i 这⾥就是指针+整数
}
return 0;
}
5.2指针-指针
//指针-指针
#include <stdio.h>
int my_strlen(char *s)
{
char *p = s;
while(*p != '\0' )
p++;
return p-s;
}
int main()
{
printf("%d\n", my_strlen("abc"));
return 0;
}
5.3 指针的关系运算
//指针的关系运算
#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int *p = &arr[0];
int i = 0;
int sz = sizeof(arr)/sizeof(arr[0]);
while(p<arr+sz) //指针的⼤⼩⽐较
{
printf("%d ", *p);
p++;
}
return 0;
}
6.转移表
函数指针数组的⽤途:转移表
转移表是一种在C语言中用于优化多分支条件的技术。它通常用于替代长串的if-else语句或switch语句,从而提高代码的执行效率。转移表使用一个数组来存储函数指针或跳转地址,根据输入的条件值直接跳转到相应的函数或代码块,而不需要逐个比较条件。
以下是一个简单的例子,展示如何使用转移表来实现一个简单的计算器,根据用户输入的操作符执行相应的操作:
#include <stdio.h>
int add(int a, int b) {
return a + b;
}
int subtract(int a, int b) {
return a - b;
}
int main() {
int (*operation)(int, int); // 声明一个指向函数的指针
operation = add; // 将指针指向add函数
printf("Addition: %d\n", operation(5, 3));
operation = subtract; // 将指针指向subtract函数
printf("Subtraction: %d\n", operation(10, 4));
return 0;
}
#include <stdio.h>
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
}
int div(int a, int b)
{
return a / b;
}
int main()
{
int x, y;
int input = 1;
int ret = 0;
do
{
printf("*************************\n");
printf(" 1:add 2:sub \n");
printf(" 3:mul 4:div \n");
printf(" 0:exit \n");
printf("*************************\n");
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
printf("输⼊操作数:");
scanf("%d %d", &x, &y);
ret = add(x, y);
printf("ret = %d\n", ret);
break;
case 2:
printf("输⼊操作数:");
scanf("%d %d", &x, &y);
ret = sub(x, y);
printf("ret = %d\n", ret);
break;
case 3:
printf("输⼊操作数:");
scanf("%d %d", &x, &y);
ret = mul(x, y);
printf("ret = %d\n", ret);
break;
case 4:
printf("输⼊操作数:");
scanf("%d %d", &x, &y);
ret = div(x, y);
printf("ret = %d\n", ret);
break;
case 0:
printf("退出程序\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
总结
指针是C语言中的核心概念,掌握指针的使用可以提高程序的灵活性和效率。了解指针的基本操作、内存分配、数组、函数和高级概念,对于编写高质量的C代码至关重要。同时,正确使用指针也需要注意内存管理和安全性,避免出现悬挂指针、内存泄漏等问题。