数组的首地址与数组的首地址取地址

Scanf的困惑

在学习“鸟叔”的Linux教程时碰到了一个奇怪的事情。例程给的代码如下:
#include <stdio.h>
#define pi 3.14159
char name[15];
float angle;
void haha(char name[]);
int main(void)
{
    printf ("\n\nPlease input your name: ");
    scanf  ("%s", &name );
    printf ("\nPlease enter the degree angle (ex> 90): " );
    scanf  ("%f", &angle );
    haha( name );
}

看起来没什么问题,但编译时会报如下错误:

main.c:12:10: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[15]’ [-Wformat=]
  scanf  ("%s", &name );

大概就是说scanf的参数类型不对,但字符串不是这样输入的吗?
在网上看了一下,正确的方法好像是 scanf(“%s”,name)。修改之后,果然没警告了。回想一下,当时在有警告的情况下编译也是通过的,而且程序运行正常,那么这个name和&name到底有什么区别?


数组名的含义

这是数组的定义:

char name[15];

name 是数组名,作为变量,name也是数组的首地址,也就是0xXXXXXXX。。。的东西。
& 是取地址符合,从字面上的意思来看,&name是取数组首地址的地址。两者有什么关联?通过下面这个程序看一下:

#include <stdio.h>

int main(void)
{
    int name[10]={0};
    int *p=name,*q=&name;
    printf("%p,%p\n",p,q);
}

运行后输出结果如下:

root@obama-ubuntu:/home/obama/project/main# ./main 
0x7fff5abfcd20,0x7fff5abfcd20

也就是说两者的值是一样的,对于scanf来说,两者是等价的。
不过对于name[]这个数组来说,意义却又不一样。


name[],name,&name

运行如下代码:

#include <stdio.h>

int main(void)
{
    int name[10]={0};
    int *p=name+1,*q=&name+1;
    printf("%p,%p\n",p,q);
}

我在把name和&name赋值给指针之前,各给其加1,按照常理,相当于到了name[1]的地址,然而结果如下:

root@obama-ubuntu:/home/obama/project/main# ./main 
0x7ffed1023714,0x7ffed1023738

0x7ffed1023710应该是数组的地址,0x7ffed1023714是name[1]的地址,那0x7ffed1023738呢?
数组name[10]长度是10,系统的一个整数占4个字节,所以
0x7ffed1023738 = 0x7ffed1023710 + 40字节 = 0x7ffed1023710 + 10个整形变量
由此可以看出&name+1实际上是name[10]这个整个数组的地址加上了整个数组的长度。不知道官方语言该怎么说,既然name叫name[10]的首地址,干脆就叫&name为name[10]的数组地址吧!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章