博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C语言基础---数组、指针之间的相同与不同
阅读量:2393 次
发布时间:2019-05-10

本文共 3140 字,大约阅读时间需要 10 分钟。

文章目录

1. 不同之处

  • 数组名不可以改变,而指向数组的指针是可以改变的。
  • 指针指向字符串,此时的字符串是不能改变的;而字符数组定义的字符串,字符是可以改变的。
  • 求数组长度时,借用数组名可求得数组长度,而借用指针却得不到数组长度。


1.数组名的指向不可以改变,指向数组的指针可以改变

遍历方式一:

#include 
int main(void){
int a[5] = {
0, 1, 2, 3, 4 }, * p = a; char i; // 数组遍历方式一 for (i = 0; i < 5; i++) {
printf("a[%d] = %d\n", i, *p++); } return 0;}
a[0] = 0a[1] = 1a[2] = 2a[3] = 3a[4] = 4

数组遍历方式一:使用指针遍历数组元素,*p++等价于*(p++),即指针指向的地址每次后移一个单位,然后再取地址上的值。这里的一个单位是sizeof(int)个字节。

遍历方式二:(错误)

#include 
int main(void){
int a[5] = {
0, 1, 2, 3, 4 }, * p = a; char i; // 数组遍历方式二 for (i = 0; i < 5; i++) {
printf("a[%d] = %d\n", i, *a++); } return 0;}
  • error: value required as increment operand
  • 因为数组名的指向是不可以改变的,使用自增运算符自增就会改变其指向,这是不对的,数组名只能指向数组的开头。

遍历方式二:(正确)

#include 
int main(void){
int a[5] = {
0, 1, 2, 3, 4 }, * p = a; char i; // 数组遍历方式二 for (i = 0; i < 5; i++) {
printf("a[%d] = %d\n", i, *(a+i)); } return 0;}
  • *(a+i)相当于是指针通过偏移量,找到具体的值,而不是改变指针本身
  • *(a+i)与a[i]是等价的


2.字符串的2种初始化方式

//字符串定义方式一char str[] = "happy";//字符串定义方式二char *str = "happy";
  • 方式一:字符串中的字符是可以改变的。如可以使用类似str[3]=’q’这样的语句来改变其中的字符。原因就是:这种方式定义的字符串保存在全局数据区或栈区,是可读写的。
  • 方式二:字符串中的字符是不可以改变的。原因就是:这种方式定义的字符串保存在常量区,是不可修改的。


3.组名可求得数组长度,而指针却得不到数组长度

#include 
int main(void){
int a[] = {
0, 1, 2, 3, 4 }, * p = a; char len = 0; // 求数组长度方式一 printf("方式一:len=%d\n", sizeof(a) / sizeof(int)); // 求数组长度方式二 printf("方式二:len=%d\n", sizeof(p) / sizeof(int)); return 0;}
方式一:len=5方式二:len=1
  • 方式一:借用数组名来求数组长度,可求得数组有5个元素,正确。
  • 方式二:借用指针求数组长度,求得长度为1,

错误。原因是:

  • p只是一个指向int类型的指针,编译器不知道其指向的是一个整数还是指向一个数组。
  • sizeof(p)求得的是p这个指针变量本身所占用的字节数,而不是整个数组占用的字节数。
  • 对于数组 a,它的类型是 int [6],表示这是一个拥有 6 个 int 数据的集合,1 个 int 的长度为 4,6 个 int 的长度为 4×6 = 24,sizeof 很容易求得。
  • 对于指针变量 p,它的类型是 int *,在 32 位环境下长度为 4,在 64 位环境下长度为 8。
  • 归根结底,a 和 p 这两个符号的类型不同,指代的数据也不同,它们不是一码事,sizeof 是根据符号类型来求长度的,a 和 p 的类型不同,求得的长度自然也不一样。

编译器在编译过程中会创建一张专门的表格, 用来保存名字以及名字对应的数据类型、地址、作用域等信息。sizeof 是一个操作符,不是函数,使用 sizeof 时可以从这张表格中查询到对应符号的长度。

以上内容,来源博文:



2. 相同之处

1.使用索引的时候

1 2 3
a[i] = p[i] *(p+i) = *(a+i) *p + 1 = *a + 1
#include 
int main(void){
int a[] = {
1, 2, 3, 4, 5 }, * p, i = 2; p = a; printf("p[i]---------%d \n", p[i]); printf("a[i]---------%d \n", a[i]); printf("\n"); printf("*(p + i)---------%d \n", *(p+i)); printf("*(a + i)---------%d \n", *(a+i)); printf("\n"); printf("*p + i---------%d \n", *p + i); printf("*a + i---------%d \n", *a + i);}
p[i]---------3a[i]---------3*(p + i)---------3*(a + i)---------3*p + i---------3*a + i---------3
  • 取下标操作符 [ ]是建立在指针的基础上,它的作用是使一个指针和一个整数相加,产生出一个新的指针,然后从这个新指针(新地址)上取得数据;
  • 取下标操作符的两个操作数是可以交换的,它并不在意操作数的先后顺序。如果希望访问第 3 个元素,那么可以写作 a[3],也可以写作 3[a]
  • a[3] 等价于 *(a + 3),3[a] 等价于 *(3 + a),仅仅是把加法的两个操作数调换了位置。
  • 使用下标时,编译器会自动把下标的步长调整到数组元素的大小。数组 a 中每个元素都是 int 类型,长度为 4 个字节,那么 a[i+1]和 a[i]在内存中的距离是 4(而不是 1)。


2.数组作为函数参数的时候

  • 把作为形参的数组和指针等同起来是出于效率方面的考虑。
  • 数组是若干类型相同的数据的集合,数据的数目没有限制,可能只有几个,也可能成千上万。如果要传递整个数组,无论在时间还是内存空间上的开销都可能非常大。而且绝大部分情况下,我们其实并不需要整个数组的拷贝,我们只想告诉函数在那一时刻对哪个特定的数组感兴趣。
#include 
void func(char arr[]) {
arr[2] = 'd'; printf("arr[2]--------%c \n", arr[2]);}int main(){
char arr[] = "abcd"; func(arr); // 此时,将数组名传递给函数,就是代表了数组的指针}
arr[2]--------d

以上博文,来源:

转载地址:http://hxeab.baihongyu.com/

你可能感兴趣的文章
Eclipse LUNA配置TomCat(非j2ee版本)
查看>>
树莓派安装mysql-srver报错 404 not found!
查看>>
Ubuntu 14.04LTS 下安装.net框架
查看>>
Eclipse 配置Groovy语言环境 && Java工程运行Groovy
查看>>
人工智能术语表
查看>>
Tensorflow Python API 翻译(sparse_ops)
查看>>
Tensorflow Python API 翻译(math_ops)(第一部分)
查看>>
Tensorflow Python API 翻译(math_ops)(第二部分)
查看>>
Tensorflow Python API 翻译(array_ops)
查看>>
Tensorflow Python API 翻译(constant_op)
查看>>
金融套利策略:理解统计套利的工作原理
查看>>
利用 TensorFlow 入门 Word2Vec
查看>>
课程 | 浅析数据标准化和归一化,优化机器学习算法输出结果
查看>>
多任务学习与深度学习
查看>>
利用 TensorFlow 一步一步构建一个多任务学习模型
查看>>
使用数据驱动进行配对交易:简单交易策略
查看>>
量化交易:相关系数
查看>>
课程---程序员炒股,如何计算股票投资组合的风险和收益
查看>>
人工智能资料库:第1辑(20170105)
查看>>
人工智能资料库:第2辑(20170106)
查看>>