[基础]关于extern指针和数组的用法

之前有在外面面试,遇到一题如下:

filea.c
char *p = "abcdefg";

fileb.c
extern char p[];
printf("p[0]=%d
", p[0]);
result=?

当时只是纠结于printf中的%d打印char类型数据,会不会按地址将abcd这四个字节的数据打印出来,所以给出的答案是:0x61626364. 

类似的还有这种做法:

filea.c
char p[10];

fileb.c
extern char p[];
extern char *p;
p[0] = ?

上面这个char p[10], p只是个别名,下面的extern char *p提取p的地址可能是0,然后对p[0]赋值可能导致程序崩溃。

之后,回来查了些资料,写了个代码试了下:

filea.c

char *str = "abcdefg";

fileb.c

#include "stdio.h"

extern char str[];
char *str2 = "abcdef";


void main(void)
{
    int i = 0;
    
    printf("str1:addr=0x%08x, %d, %d, %d
", (unsigned int)str, str[0], str[1], str[2]);
    
    printf("str2
");
    for(i = 0; i < sizeof(str2); i++)
    {
        printf("[%d]=%c ", i, str2[i]);
    }
}

 Makefile

objects = filea.o fileb.o
hello:$(objects)
    gcc -o hello $(objects)
filea.o: filea.c
fileb.o: fileb.c
clean:
    rm hello $(objects)

Result:

str:addr=0x00601048, -52, 6, 64
str2
[0]=a [1]=b [2]=c [3]=d [4]=e [5]=f [6]= [7]=s %

可以看出str的输出并不是我们想要的。

为什么呢?

首先,关于指针和数组名

  • 系统会为“指针名”分配4个字节的内存空间。存放指针的内存空间和该内存中存放的数据,前者为存放指针的地址,后者为存放有效数据(如abcdef)的地址。
  • 而数组名则不会,数组名只是一块存放数据地址空间的别名。

其次,由于在fileb.c中extern char str[]; str被申明为数组,那么str就是代表一块地址空间的别名,也就是存放str指针地址空间的别名,而不是上面说道的有效数据的地址空间,所以str[0]只是存放abcdef地址空间的值。

结论:使用声明和定义要匹配。

原文地址:https://www.cnblogs.com/aaronLinux/p/6390511.html