C指针总结_20150920

本文详细阐述了C语言中指针的概念、使用方法及注意事项,包括指针变量的定义、指向数组和字符串的指针、作为函数参数的指针、指针数组和指向函数的指针等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C指针总结

  指针其实是内存单元地址在高级语言中的另一种叫法,地址也是数据,存放这种数据的变量就是指针变量,简称指针。变量的地址称为变量的指针,指变量存放空间的首地址。

(NOTE:指针变量,即指针,只能存放地址)

指向变量的指针

  如果指针变量p的值恰好是变量a的地址,就说指针变量p指向了变量a。C语言规定一个指针变量只能指向同种类型的变量,比如

int *p1;     //定义指针变量p1,只能指向整型变量
char *p2;    //定义指针变量p2,只能指向字符型变量

  指针变量的定义格式类型名 *变量名1, *变量名2, ...;其实比较好理解,只需注意区分指针变量的类型和指针所指向变量的类型。指针变量的类型明确指出它能存放什么类型变量的地址,而不是它能存放什么类型的数据(指针只能存放地址),例如

int *p1, *p2;   //定义了两个指向整型数据的指针p1,p2

其中,指针变量p1、p2的类型都是int *,而不是int。所以初学者需要特别注意下面几条语句的使用

int* p1, p2;    //错误,虽然指向整型的指针变量类型是int*,但不能这样使用,可以理解为*自动与变量名匹配而不是与类型名匹配
int *p1, *p2, a;    //正确,定义了指向整型的指针变量p1、p2和整型变量a

指向数组的指针

  数组是若干个相同类型变量的集合,在内存中占用一片连续的地址空间。按照指针的概念,数组在内存中的起始地址就是数组的指针,而数组元素的地址称为数组元素的指针。C语言规定,数组名就是数组的指针,代表数组在内存空间的首地址,同时也指向数组的第一个元素。

(NOTE:数组名,即数组的指针,是地址常量,不能更改)

int *p, data[10];
p = data;   //指针变量p指向整型数组data[10]
printf("%d", *p);    //输出data[0]的值
printf("%d", *(p+2));   //输出data[2]的值

  可以看到指针和整数执行算术运算后得到一个新的指针,那么它指向哪里呢?如果对字符指针加1,运算结果产生的指针指向内存中下一个字符。如果对整型指针加1,运算结果产生的指针指向内存中下一个整数,即移动4个字节而不是1个字节。也就是说,当指针和整数执行算术运算后,整数在运算时始终根据“合适的大小”(指针所指向变量的类型在内存中占用的字节数)进行调整,这个调整便是把整数值和“合适的大小”相乘。在上例中p+2相当于指针后移了8个字节(整型变量在内存中占4个字节)

(NOTE:C不会检查数组的下标溢出,所以针对数组使用下标引用或者间接访问操作一定要特别小心)

指向字符串的指针

  C使用字符数组存放字符串,和指向整型数组的指针一样可以使用字符指针指向字符串常量,这时指针代表字符数组(字符串)在内存中的起始地址。

char *str = "I'm very happy.";

等价于

`char *str, temp[] = "I'm very happy.";`
`str = temp;`

当直接使用字符指针指向字符串常量时,实际上系统隐含定义了一个无名字符数组来存放字符串,字符指针指向了这个无名数组,而不是字符指针存放了字符串。

指针作为函数的参数

  指针变量作为函数参数时,同样是从实参单向传递指针变量的值给形参,也即形参得到实参值的一份copy,但由于实参变量是指针,它的值是某个变量的内存地址,所以形参的值也是这个变量的内存地址。需要特别注意的是,这时实参和形参作为变量在内存中占用不同的内存单元,但是具有相同的值,即指向相同的内存单元,使用间接访问操作符*可以得到相同的值。

(1)使用间接访问操作改变形参所指向变量的值,则实参所指向变量的值也发生变化

(2)改变形参的值并不会改变实参的值以及实参所指向变量的值

见下例

#include <stdio.h>

//交换两个形参变量的值,并不会改变实参的值和实参所指向变量的值
void swap(int *a, int *b)
{
    int *c;
    c = a;
    a = b;
    b = c;
    printf("swap: a=%d, b=%d\n", *a, *b);
}

int main()
{
    int a, b;
    scanf("%d%d", &a, &b);
    printf("main_1: a=%d, b=%d\n", a, b);
    swap(&a, &b);
    printf("main_1: a=%d, b=%d\n", a, b);
    return 0;
}

输入

3 8

程序输出

main_1: a=3, b=8
swap: a=8, b=3
main_1: a=3, b=8

  可以见到,虽然使用指针变量作为函数参数,但在被调函数内交换的是两个指针变量,而不是指针所指向的变量,因此实参所指向变量的值并未发生改变。

#include <stdio.h>

//交换两个形参所指向变量的值,实参所指向变量的值也发生改变
void swap(int *a, int *b)
{
int c;
c = *a;
*a = *b;
*b = c;
printf("swap: a=%d, b=%d\n", *a, *b);
}

int main()
{
int a, b;
scanf("%d%d", &a, &b);
printf("main_1: a=%d, b=%d\n", a, b);
swap(&a, &b);
printf("main_1: a=%d, b=%d\n", a, b);
return 0;
}

输入

3 8

程序输出

main_1: a=3, b=8
swap: a=8, b=3
main_1: a=8, b=3

  这次使用指针变量作为函数参数,且在被调函数内交换指针所指向的变量,因此实参所指向变量的值发生改变。

指针数组

  把相同类型的指针变量存放在一个数组中,便构成了指针数组。一般字符指针数组用的比较多,多用于存放不等长的字符串。如下

char *log[10];      //定义字符指针数组,存放日志信息

数组log[10]的元素类型是char *,即字符指针,可以指向不等长的字符串。比如

char *log[10] = {"mac new 00:e0:4c:8b:08:47", "mac old 00:e0:4c:8b:25:eb", "arp spoof 192.168.1.26", ...};

指向函数的指针

  函数在编译后运行时,会被分配一块内存区域,这个内存区的起始地址便是函数的入口地址,也即函数的指针。指向函数的指针的定义如下,

返回值类型 (*指针变量名)(参数类型列表);
double (*p)(float, float);  //定义了一个函数指针p,指向的函数有两个float型参数且返回double型数据

为方便理解,可以这样想: (实际编译是通不过的,存在语法错误)

double(float,float) *p; //定义一个double(float,float) *型的指针p(仅限于理解,实际存在语法错误)

(NOTE:(*p)中的括号是必需的,因为*的优先级低于函数定义的(),和下面要介绍的返回指针的函数有区别)

返回指针的函数

  函数同样可以返回指针类型,定义如下

类型名 *函数名(参数列表)
{函数功能}

比如

int *fun(int a, int b); //定义一个返回int *型数据的函数fun(int,int)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值