C中的数组与指针问题
2016-03-18 15:11
375 查看
反复在数组名与指针上犯错误,特记录下。
*(p+1)? *(q-1) ?
答案是 3, 5。这里主要涉及的问题就是指针参与运算时,它的地址是怎么增加的,也就是它的地址变化单位。首先,明确一点,指针参与算术运算时,指针地址变化是:offset * 指针指向对象长度。例如,上面的代码中,p, q都是int *类型的,那么指针对象长度就是4,同理,char *ptr, 它的就是1。再看看p q此时的指向,关键点就是对于数组名,a和&a有和不同?它们两的值其实是一样的,但是指向的数据类型就不一样了,a指向的是数组第一个元素,也就是说a = &(a[0]),而&a呢,指向的数据类型是int a[5]这样一个数组,而a[0]是个int型数据,所以,a: int * , &a: int [5] *,那么它们指向对象的长度就分别是4,和20了。问题解决。
此外,sizeof(a) ? sizeof(&a) ?
答案是 20, 4。sizeof发生在程序的编译阶段,求指定对象占的存储空间。a对象就是整个数组,&a对象就是指向这个数组对象的指针。所以答案就是20, 4。貌似这一切都是一些规定性的东西,说不出一个好的彻底的理由。
还有一点就是数组名是一个常量指针。额,不是没用const修饰吗?其实说是常量指针不够严谨,应该是只读指针。被const修饰意味着只读。看看其汇编就明白了。
这个数组的定义位于上面汇编的38-50行,可以看到41行对此段声明为rodata。未完,39-40行的修饰应该是针对标签 .L3。熟悉下汇编后再来完善。
为什么不能修改数组名的值?从C语言的角度,如果修改了数组名的值,例如a++,也就是a = a + 1;那么此后,数组a将失去其基地址,后面的代码将无法访问a[0]了。也许你会说,a = a -1;不就找到了吗?但是每次修改后又要恢复,岂不是极其麻烦,容易导致编程的人疏漏出错。所以编译器干脆规定不允许修改。
int a[] = {1,2,3,4,5}; int *p, *q; p = (int *)(a+1); q = (int *)(&a-1);
*(p+1)? *(q-1) ?
答案是 3, 5。这里主要涉及的问题就是指针参与运算时,它的地址是怎么增加的,也就是它的地址变化单位。首先,明确一点,指针参与算术运算时,指针地址变化是:offset * 指针指向对象长度。例如,上面的代码中,p, q都是int *类型的,那么指针对象长度就是4,同理,char *ptr, 它的就是1。再看看p q此时的指向,关键点就是对于数组名,a和&a有和不同?它们两的值其实是一样的,但是指向的数据类型就不一样了,a指向的是数组第一个元素,也就是说a = &(a[0]),而&a呢,指向的数据类型是int a[5]这样一个数组,而a[0]是个int型数据,所以,a: int * , &a: int [5] *,那么它们指向对象的长度就分别是4,和20了。问题解决。
此外,sizeof(a) ? sizeof(&a) ?
答案是 20, 4。sizeof发生在程序的编译阶段,求指定对象占的存储空间。a对象就是整个数组,&a对象就是指向这个数组对象的指针。所以答案就是20, 4。貌似这一切都是一些规定性的东西,说不出一个好的彻底的理由。
还有一点就是数组名是一个常量指针。额,不是没用const修饰吗?其实说是常量指针不够严谨,应该是只读指针。被const修饰意味着只读。看看其汇编就明白了。
.arch armv4t .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 2 .eabi_attribute 30, 6 .eabi_attribute 18, 4 .file "a.c" .text .align 2 .global main .type main, %function main: @ Function supports interworking. @ args = 0, pretend = 0, frame = 24 @ frame_needed = 1, uses_anonymous_args = 0 @ link register save eliminated. stmfd sp!, {r4, fp} add fp, sp, #4 sub sp, sp, #24 ldr r3, .L3 //ldr伪指令,将数组所在段的标签地址加载到r3,.L3这个标签可以理解为数组名 sub ip, fp, #24 mov r4, r3 ldmia r4!, {r0, r1, r2, r3} stmia ip!, {r0, r1, r2, r3} ldr r3, [r4, #0] str r3, [ip, #0] mov r3, #0 mov r0, r3 sub sp, fp, #4 ldmfd sp!, {r4, fp} bx lr .L4: .align 2 .L3: .word C.0.1261 .size main, .-main .section .rodata .align 2 .type C.0.1261, %object .size C.0.1261, 20 C.0.1261: .word 1 .word 2 .word 3 .word 4 .word 5 .ident "GCC: (ctng-1.6.1) 4.4.3" .section .note.GNU-stack,"",%progbits
这个数组的定义位于上面汇编的38-50行,可以看到41行对此段声明为rodata。未完,39-40行的修饰应该是针对标签 .L3。熟悉下汇编后再来完善。
为什么不能修改数组名的值?从C语言的角度,如果修改了数组名的值,例如a++,也就是a = a + 1;那么此后,数组a将失去其基地址,后面的代码将无法访问a[0]了。也许你会说,a = a -1;不就找到了吗?但是每次修改后又要恢复,岂不是极其麻烦,容易导致编程的人疏漏出错。所以编译器干脆规定不允许修改。
相关文章推荐
- WebForm(aspx,cs,dll之间的关系)
- 使用structs2开源框架+tomcat开源服务+mysql开源数据库+微信开放接口构建考务信息推送平台
- 毕加索实现APP开起的Wellcome图片
- 使用JavaScript为Kindeditor自定义按钮增加Audio标签
- 职业生涯规划:(他______牺牲生命_______出卖组织?)
- ASP.NET TextMode 属性
- Oracle内连接、左外连接、右外连接、全外连接小总结
- 音视频的同步原理
- 使用SoapUI测试调试web service接口详细教程
- HttpHandler 实现文件下载
- 操作系统知识总结
- Linq to Sql 合并数据
- SilkTest入门快打1-录制回放
- poj 1018 dp
- 音视频同步(播放)原理
- Android学习之RecyclerView
- iOS 从git拷贝Xcode的snippets
- 压缩感知重构算法之OMP算法python实现
- 关于dev_set_drvdata()和dev_get_drvdata()
- 如何排序 MFC的CStringArray