【原创】浅谈指针(五)const和指针

前言

过了几个月再次更新。最近时间也不多了,快要期中考试了,暂且先少写一点吧。
本文仅在博客园发布,如在其他平台发现均为盗取,请自觉支持正版。

练习题

我们先来看几道题目。如果这几道题都不会的话,就先好好复习我写的前四篇文章吧,这一章是肯定看不懂的。

  • 1.使用指针编写swap函数。(经典例题)
答案

void swap(int *a,int *b){
int t=*a;*a=*b;*b=t;
}

  • 2.已知数组a[10][10],交换该数组的第1和第3行。
答案 实际上,二维数组的每一行都是一个单独的数组,二维数组的本质就是“数组的数组”。因此,可以使用memcpy进行数组拷贝。

int temp[10];
memcpy(temp,a[0],10*sizeof(int));
memcpy(a[0],a[2],10*sizeof(int));
memcpy(a[2],temp,10*sizeof(int));

const

const含义

const是constant的缩写,意为“常量”,事实上我们也经常用const定义常量。
但是在C语言(这里不是C++),const的含义是“只读变量”。也就是说,const就是普通变量。
我们做一个实验确认一下。(务必采用C语言编译)

#include<stdio.h>
int main(){
    int *p;
    const int a=5;
    printf("a..%d",a);
    p=&a;
    *p=10;
    printf("a..%d",a);
}

先说一下C++为什么不通过编译,因为C++对于类型比较严格,编译上述代码会出这个错误:

error: invalid conversion from 'const int' to 'int' [-fpermissive]
因此,如果手头只有C++环境的话,请务必开-fpermissive选项。

在C语言下,输出结果是a..5和a..10。在C++下,即使开了fpermissive,结果仍然是a..5和a..5。
我们来阅读一下程序。我们使用指针的形式,将a的地址赋值给p,那么p所指向的就是a。但是由于p不带const(const指针的问题将会于下一节叙述),*p可以被修改,那么a就理所当然被修改为10了。
但是在C++中,const就是指常量,在处理a的时候,编译器会自动的把a理解为5,不再去读取a所在的内存了。因此,即使a对应的内存被修改,a输出结果仍然为5。
如果把第二个printf语句中,a改为*p,输出为10。这再次证明了C++这一特性。

const内存区域

如果把const int a一句放到main以外成为全局变量,结果又会如何?大家可以自行尝试一下。

结果是运行时错误,segmentation fault段错误。
这是因为,全局变量的const,存储的区域是配置在内存的只读区域的,修改会出问题。而局部变量存储的区域在栈上,和其他普通变量在一起,因此可以任意修改。

如果尝试输出全局变量和局部变量的地址,我们发现,两个地址相差很远。
0x402004 0x7ffd9a34094c

const和指针

声明部分

(以下转自我之前写的C语言常见误区)
关于const和指针连在一起,经常让初学者们摸不着头脑。
例如下面几句:

const char *p
char const *p
char* const p
const char* const p

它们各有什么区别?
我这里曾经从《征服C指针》看到了几条非常好的内容,在此给大家分享一下:

因为C语言是美国人发明的,最好还是用英语来读(声明语句)。
规则:从后往前倒序,如果遇到*号,就加上“pointer to”,如果有const,就追加“read-only”。
const在前面和在后面完全相同。

例如,对const char *p进行翻译:
首先看到p:p is
然后是*:p is pointer to
然后是char:p is pointer to char
然后是const:p is pointer to read-only char
翻译为中文:p是指向只读的char的指针

按照这种方式解释,我们对上面四个语句解释如下:

p is pointer to read-only char
p is pointer to read-only char
p is read-only pointer to char
p is read-only pointer to read-only char

照这样,我们得出结论:
const char* p 和char const* p含义完全相同,表示指向的字符是不可变的。
char* const p表示指针自身不可变,指向的字符可变。
而最后一个,指向的字符和指针自身都不可变。

应用

定义字符串常量,我们一般使用:

const char *str=...

这类的语句。指向的字符是不可改变的。

但注意下面的代码:

#include<stdio.h>
#include<string.h>
struct test{
	int a,b;
	char str[10];
};
int main(){
    const struct test a={1,2,"hello"};
	strcpy(a.str,"abc");
	printf("%s",a.str);
}

虽然结构体a是const的,因此str本身不可改变,但是str指向的字符仍然可以改变!图示如下:

函数参数的const

比较简单。例如strcpy的声明:

void strcpy(char *dest, const char *src);

在此处,const表示在函数内部,src的值不可改动。并非表示传入的参数一定是常量。
很多函数都包含输入参数和输出参数。与其使用繁杂的注释,例如:

/*
src (i) 参数提供的输入字符串
dest (o) 复制到的字符串
*/

使用i,o等标记,还不如使用const,后者在函数中不小心修改src的时候,还会发出警告。
以上参考《征服C指针》。
全文完。

posted @ 2021-10-24 09:26  计算机知识杂谈  阅读(355)  评论(3编辑  收藏  举报