先看一下下面这个程序:
#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++来说,a是0x0012ff6c,那a+1就是0x0012ff6c+1*sizeof(int) = 0x0012ff6c + 4 = 0x0012ff70。
同理,&a +1就是&a + 5*sizeof(int) = 0x0012ff6c + 20 = 0x0012ff80才对,为什么在VC++中会是0x0012ff6d呢?这点我也不知道。
但是在gcc中,&a是0xbfb67aa0, &a+1 是0xbfb67ab4,也就是&a + 5*sizeof(int).。
反正我认为gcc中的是正确的,至于你怎么认为,那就不关我的事了。
回到我们一开始的问题,现在知道程:1错误是什么原因了吧,
毫无疑问, p1, p2都是数组指针,指向的是整个数组,而虽然&a 与 a的值相同,但是意义不同。
对于p2,它指向的是一个包含5个int类型元素的数组,但是它的右值却是数组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)
剩下的自己想去~~~