`
cloudtech
  • 浏览: 4594624 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

关于C语言指针和数组的深入探讨

 
阅读更多

我们先看一个例子:

A.int a[3][4];

B.int b[12];

C.int (*p)[12];

他们分别是一个二维数组,一个一维数组,一个指向一维数组的指针。我们知道整型,用int表示,字符用char表示,一些基本的类型都有字面上的一种表示,那么像int a[3][4]这种它的字面上的表示是什么呢?编译器可不知道什么“指向整型的二维数组”之类的东西,实际上他们有自己的类型,不过不像基本类型那样统一明确。很大程度上,他们在不同编译器中给出的类型表示是不同的,如vc下面的int [3][4],gcc下面的A3_A4_i,但是他们传递的意义是一样的。

我们知道数组可以跟指针转换。转换的本质就是“降维“,那么:

int [1][2][3]==> int (*)[2][3]

int [3][4] ==> int (*)[4]

int [12] ==> int *

还有一个事实就是,C语言在赋值时要求类型匹配(当然很多同学都无视这些警告 -_-!)。所以当B赋值给C时,就会报警告,因为B类型为int [12],而C为int (*)[12],所以正确的赋值时p = &b,因为&b的类型就是int (*)[12],一切就OK了。

这里不得不提一个问题就是a[3][4]降维之后为什么’3’没了,’4’还在?因为在内存布局上,一个二维数组(高维道理一样),是以行为布局单位,一行挨一行的放。在这个例子里,我们知道3为行数,4为列数,所以降维意味着我们能看得更细,我们就看到了它在内存里是一行一行的(当然有的人眼更厉害,他可以看到每个字节。。。这是另一种情况,我们后面会说)。

这里分几点来说:

1. 赋值与比较

C语言属于强类型语言,类型检查比较严格,类型不匹配的会报警告,但是有些情况除外,即转换形式(如数组转换成等价的指针形式)一致的两个类型,是兼容的。

例如:int (*p)[4]和int a[3][4],这时p=a的赋值时正常的,原因就是int [3][4]其等价的指针形式为int (*)[4],而这个跟p的类型是相符的。

2. 加减运算

在开始的那个例子中,int a[3][4]的类型是int [3][4],那么a + 1呢?

这里的a要转换为等价的指针形式来运算(数组加减。。。没听说过!),那个a的指针形式就是int (*)[4],运算时就要根据这个类型来算。另外一点,指针加减中的数字,是一个数量的意思,意思是加减n * sizeof(type),注意这里说的type是指针指向的类型,如本例,a是int (*)[4]类型,它指向的是int [4]

类型,那么加1,就以为这加1 * sizeof(int [4]),即16字节。

3. 取一个元素(就是前面所说的那种好眼力)

假设int a[3][3] = {{1,2,3}, {4,5,6},{7,8,9}},我们知道a[2][1]可以取到值8,那么*(*(a+2)+1)为什么也能取到这个值呢?有了上面所说的,理解应该比较简单了。我们最终要取得一个int,而现在摆在眼前的是int [3][3]类型,那么我们就可以通过一步步转换和降维来做到。a[2][1],位于第3行中的第2个数(位于二维层面上的三行二列的位置),所以我们先定位第3行,再在这一行中定位第2个数就行了。

a的指针等价形式为int (*)[3],所以a+2,就是从开始位置,找到2*sizeof(int [3]),即第三行(记住在内存布局上,是一行一行挨在一起放的),此时a+2的类型还是int (*)[3],因为指针上加减数字并不改变类型。此时*(a+2)就是为int (*)[3]的指针类型取内容,很明显得到的类型就是int [3]了。因为*(a+1)的类型为int [3],其等价的指针形式就是char *,自然*(a+1)+1,就是指向int [3]数组中的第二个元素,此时的类型还是char *,那么拿到最终的元素,用*来取内容就行了,也就是*(*(a+2)+1)。

编译器就是按照这些规则来处理千变万化的表达式,而只要按照规则,处理起来就是一样的道理,类似递归那样一层层处理下去。大家在碰到类似的情况时,按照这些方法去理解,去处理,问题就好解决了。

分享到:
评论

相关推荐

    C语言中数组与指针的探讨.pdf

    C语言中数组与指针的探讨

    C语言中数组与指针学习探讨.pdf

    C语言中数组与指针学习探讨.pdf

    C语言中数组与指针关系的探讨.pdf

    C语言中数组与指针关系的探讨.pdf

    描述一下C语言经典指针问答,并附带详细的解答举例说明.docx

    本文将深入探讨C语言指针的相关概念,帮助你更好地理解和运用它们。 C语言指针是程序设计中最重要的概念之一。它可以帮助你更好地管理内存,提高程序的效率,让你更加高效地编写代码。在这个问答集中,你将会学习到...

    短时间攻破c语言指针

    本书为你详尽探讨指针的使用,什么是常量指针,什么是指针常量,数组同指针有什么区别,什么叫地址传递和指针传递,函数指针式怎么一回事。本书通俗易明,图文并茂,语言精简易懂,有理论也有实践部分,适合有c语言...

    C语言中指针使用技巧探讨

    本文档在某知名网站下载,要么浏览量最多,要么最新,保证精品,至少为你节约3RMB。格式为caj或者kdh需要专业阅读器打开。

    现代C语言核心特性解析,C语言编程与宠物狗互动案例分析.pdf

    接着,我们将深入探讨指针和数组,包括指针的基本概念、指针的算术运算、指针和数组的关系等等。然后,我们将介绍C语言中的结构体和联合体,以及这些数据类型在实际编程中的应用。此外,我们还将讲解C语言中的函数和...

    C语言学习笔记资源包,C语言初学者必备

    进阶知识笔记:深入探讨了指针、数组、函数、结构体等进阶知识点,帮助学习者进一步提升编程能力。 实践案例笔记:结合实际案例,让学习者通过实践掌握C语言的实际应用,培养解决问题的思维。 常见错误与调试笔记:...

    深度解析C语言中的指针

    指针是 C 语言的精华部分,也是 C 语言学习的重点和难点,正确而灵活地应用指针是学习 C 语言中最重要的环节,本文从指针的概念、运算、初始化以及与数组和函数的关系五个方面对 C 语言指针进行了分析和探讨。

    C 和指针.pdf

    本书提供与C语言编程相关的全面资源和深入讨论。本书通过对指针的基础知识和高级特性的探讨,帮助程序员把指针的强大功能融入到自己的程序中去。  全书共18章,覆盖了数据、语句、操作符和表达式、指针、函数、数组...

    C语言学习路线详细描述规划.docx

    接着,它深入探讨了控制结构、函数、数组、指针、结构体等核心概念,然后继续扩展到文件操作、库函数使用、数据结构、算法,以及与操作系统和网络编程相结合的高级主题。 此外,学习路线还包含实际项目实战,旨在...

    5分钟内了解C语言的指针

    指针、引用和取值 什么是指针?什么是内存地址?什么叫做指针的取值?指针是一个存储计算机内存地址的变量。在这份教程里“引用”表示计算机内存地址。从指针指向的内存读取数据称作指针的取值。指针可以指向某些...

    吕鑫:最博大精深的C语言视频教程 第14天 【第1堂课】指针变量对内存数据的操作

    1、探讨字符串指针变量与字符串数组的区别; 2、探讨指针变量的偏移与距离;

    吕鑫:最博大精深的C语言视频教程 第14天 【第2堂课】字符串拷贝函数实现原理及应用

    1、讲解通过指针变量实现字符串拷贝函数的代码编写方法; 2、探讨字符串数组和字符串常量在字符串复制过程中的各种情况;

    JavaScript中对循环语句的优化技巧深入探讨

    循环是所有编程语言中最为重要的机制之一,几乎任何拥有实际意义的计算机程序(排序、查询等)都里不开循环。 而循环也正是程序优化中非常让人... javascript 的for语法继承自c语言,for循环的基本语法有两种使用方法。

    C++反汇编视频教程(代码+课件+视频全套价值300元的付费教程)

    本套课程主要探讨如何读懂 C/C++ 语言程序的反汇编代码。所谓反汇编,简单的讲就是把可执行文件的二进制编码翻译成汇编语言代码,从汇编代码中读懂原高级语言的含义。这是一套基础课程,着重讲解反汇编代码与 C/C++ ...

    华为编程开发规范与案例

    C语言中最大的特色就是指针。指针的使用具有很强的技巧性和灵活性,但同时也带来了很大的危险性。在XXX的代码中有如下一端对指针的灵活使用: ... ... _UC *puc_card_config_tab; ... ... Get_Config_Table( ...

Global site tag (gtag.js) - Google Analytics