经常听到别人说:“数组名和指针变量名是一回事”,事实真的是这样吗?
话不多说,先上一份儿代码!
================================================================
源代码1:#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char *p1 = NULL;
char *p3 = NULL;
char p2[1024] = {0};
if (NULL == (p1 = malloc(1024))) {
printf("error in malloc\n");
return -1;
}
printf("[%p]\n", &p1 );
printf("[%p]\n\n", p1 );
printf("[%p]\n", &p2 );
printf("[%p]\n", p2 );
printf("[%p]\n\n", &p2[0]);
p3 = &p2[0];
printf("[%p]\n", &p3 );
printf("[%p]\n", p3 );
return 0;
}
================================================================
运行结果打印1:
Administrator@1427-Michael ~/array
$ ./a.exe
[0x22ac4c]
[0x20010230]
[0x22a848]
[0x22a848]
[0x22a848]
[0x22ac48]
[0x22a848]
================================================================
总结:
1. { &数组名,数组名,&数组名[0] },这三者是同一个东西,都表示数组中第一个元素的地址值!!!
2. “&数组名”的功能并不等价于“&指针变量名”,尤其要注意!!!
================================================================
举例说明如果没弄清楚这二条总结所带来的危害
源代码2:
int foo(char **input)
{
char *p = *input;
if (NULL == p) {
printf("no memory to write\n"); //为了避免调用者传来一段不可写内存
return -1; // for fail
}
else {
// do something!!
return 0; // for success
}
}
int main()
{
char *p1 = NULL;
char *p3 = NULL;
char p2[1024] = {0};
if (NULL == (p1 = malloc(1024))) {
printf("error in malloc\n");
return -1;
}
p3 = &p2[0];
printf("ret is [%d]\n", foo(&p1) );
printf("ret is [%d]\n", foo(&p2) );
printf("ret is [%d]\n", foo(&p3) );
return 0;
}
================================================================
运行结果打印2:
$ ./a.exe
ret is [0]
no memory to write
ret is [-1]
ret is [0]
================================================================
再看下一段代码:
源代码3:
int foo(char *input)
{
if (input != NULL) {
printf("input is [%s]\n", input);
return 0;
}
else {
printf("empty input\n");
return -1;
}
}
int main()
{
char *p1 = "abcdefg";
char p2[] = "abcdefg";
foo(p1);
foo(p2);
return 0;
}
================================================================运行结果打印3:
$ ./a.exe
input is [abcdefg]
input is [abcdefg]
总结:
3. “数组名”和“指针变量名”在这种情况下有着一样功效。
综上:
1. { &数组名,数组名,&数组名[0] },这三者是同一个东西,都表示数组中第一个元素的地址值!!!
2. “&数组名”的功能并不等价于“&指针变量名”,尤其要注意!!!
3. “数组名”和“指针变量名”在这种情况下有着一样功效。
最后我想说,“数组名”和“指针变量名”在不同的情况下有不同的功效,所以流言被终结!
下面才是关键,为什么“数组名”和“指针变量名”有时候相同,有时候不同呢?
从第一份代码中,我们可以清楚的来了解这几个东西的具体意义到底是什么!
而第二份代码中,对于函数int foo(char **input),它期待调用者传入一个指针变量的地址值,并且这个指针变量要指向一段合法可读写内存,而不是NULL。换句话说,这个指针变量存储了那段合法可读写内存的首地址。话说得比较绕口。所以在这种情况下,传入“&数组名”和“&指针变量名”的意义就不同了,对吧!
有人说,我非得把数据弄到p2数组定义时的那块内存,有什么办法吗?答案是有的,还有两种!
第一种:
char *tmp = NULL;
tmp = p2;
foo(&tmp);
第二种:
char *tmp = malloc(1024);
foo(&tmp);
strncpy(p2, tmp, 1024);
free(tmp);
都达到了功效,把操作后的数据存入了p2的那块内存区,因为p2很可能是全局数组,所以才会有这种非要使用p2内存区的需求。
在第三份代码中,就体现了在传递参数时,“数组名”和“指针变量名”都是传递首地址值,所以相当于功效一样了。
文中难免出现错误,如果您发现了,请及时告诉我,我一有时间就会马上修改的,以免误导大家,谢谢!