C数组与指针

先看一下下面这个程序:

#include <stdio.h>

int main(int argc, char *argv[])

{

       printf ("%d \n", sizeof('A'));

 

       return 0;

}

你说输出的结果是多少?

VC++中,打印出1,而在gcc中,则打印出4

C专家编程第八章172页中,提到过:

在表达式中,每个char都会被转化成int…注意所有位于表达式中的float都会被转换成double…,由于函数参数也是一个表达式,所以当参数传递给函数的时候也会发生类型转换。具体来说,就是char short转换成int,float转换成double.

 

 

 

 

 

再论数组和指针

不多说,先来看下面这个例子:

程序1

/*=================

*

*     对于一数组a[5],被例程

*     测试a&a的差别。

*     工具:VC++

*

*=================*/

#include <stdio.h>

 

int main(int argc, char *argv[])

{

       char a[5] = {"ABCD"};

      

       char (*p1)[5] = &a;

       char (*p2)[5] = a;

 

       return 0;

}

对于以上程序,编译是否会出问题呢?

来看一下VC++中的编译情况:

c:\documents and settings\administrator\test0913.cpp(15) : error C2440: 'initializing' : cannot convert from 'char [5]' to 'char (*)[5]'

        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

Error executing cl.exe.

很明显,编译是不通过的。在gcc中,编译是可以通过的,但是有个警告,来看一下

[root@localhost file]# gcc -g testb.c -o testb

testb.c: In function ‘main’:

testb.c:9: warning: initialization from incompatible pointer type

那么是什么原因呢?

首先我们先来看一下对于数组a;

a&a有和异同?

a是数组a首元素的首地址,也就是a[0]的地址,相当于&a[0];

&a是数组a的首地址,也就是整个数组的首地址。

那现在我们还是对a&a有何差别不是很了解啊,别着急,下面我们通过例子来说一下:

程序2

2       #include <stdio.h>

3

4       int main(int argc, char *argv[])

5       {

6               int a[5];

7

8               return 0;

9       }

以上这个程序,在VC++中和gcc中是不一样的,在VC++中,按照我的理解&a表示整个数组的首地址,那么&a+1就是下一数组的首地址了。这样说不好理解,先来看一下在VC中,a, a+1, &a, &a+1是什么关系?

而在gcc中,用gdb调试可以看到

(gdb) x a

0xbfb67aa0:     0x00000001

(gdb) x a+1

0xbfb67aa4:     0x00000002

(gdb) x &a

0xbfb67aa0:     0x00000001

(gdb) x &a+1

0xbfb67ab4:     0xbfb67ad0

可见,在VC++中和gcc中的是不一样的,依照我自己的理解,我觉得gcc中的符合我的见解。

a+1就是a +1*sizeof(int),VC++来说,a0x0012ff6c,a+1就是0x0012ff6c+1*sizeof(int) = 0x0012ff6c + 4 = 0x0012ff70

同理,&a +1就是&a + 5*sizeof(int) = 0x0012ff6c + 20 = 0x0012ff80才对,为什么在VC++中会是0x0012ff6d呢?这点我也不知道。

但是在gcc中,&a0xbfb67aa0 &a+1 0xbfb67ab4,也就是&a + 5*sizeof(int).

反正我认为gcc中的是正确的,至于你怎么认为,那就不关我的事了。

 

回到我们一开始的问题,现在知道程:1错误是什么原因了吧,

毫无疑问, p1 p2都是数组指针,指向的是整个数组,而虽然&a a的值相同,但是意义不同。

对于p2,它指向的是一个包含5int类型元素的数组,但是它的右值却是数组a首元素的首地址,类型不匹配。因此是会出问题的。

那么,对于上述程序, p1+1的值是多少呢?p2+1呢?

gdb调试观察一下:

(gdb) p p1

$1 = (char (*)[5]) 0xbffbaef7

(gdb) p p1+1

$2 = (char (*)[5]) 0xbffbaefc

(gdb) p p2

$3 = (char (*)[5]) 0xbffbaef7

(gdb) p p2+1

$4 = (char (*)[5]) 0xbffbaefc

 (gdb)

 

下面,把程序改一改,改成下面这个样子,来看一下吧

     2  #include <stdio.h>

     3

     4  int main(int argc, char *argv[])

     5  {

     6          char a[5] = "ABCD";

     7

     8          char (*p3) = &a;

     9          char (*p4) = a;

    10

    11          return 0;

12  }

 很明显,p3的数据类型与&a或者a的数据类型都不一致,下面还是先看一下编译器怎么说

gcc中,是可以编译通过,而在VC++中,是编译不通过的,

gdb中,

(gdb) p p3

$5 = 0xbff38677 "ABCD"

(gdb) p p3+1

$6 = 0xbff38678 "BCD"

(gdb) p p4

$7 = 0xbff38677 "ABCD"

(gdb) p p4+1

$8 = 0xbff38678 "BCD"

gdb) x p3

0xbff38677:     0x44434241

(gdb) x p3+1

0xbff38678:     0x00444342

(gdb) x p4

0xbff38677:     0x44434241

(gdb) x p4+1

0xbff38678:     0x00444342

(gdb)

剩下的自己想去~~~

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值