您的位置:首页 > 其它

C中的数组与指针问题

2016-03-18 15:11 375 查看
  反复在数组名与指针上犯错误,特记录下。

  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;不就找到了吗?但是每次修改后又要恢复,岂不是极其麻烦,容易导致编程的人疏漏出错。所以编译器干脆规定不允许修改。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: