int (*p)[10]=s 和 int (*o)[5]=&s 有什么区别?

What is the difference between int (*p)[10]=s and int (*o)[5]=&s?

基于约定 int (*o)[5]=&s;是指针 o 指向具有 5 个元素的数组的正确方法。

我们也可以在这个语句中写这个s

int (*p)[10]=s; 

但为什么更喜欢

&s at int (*o)[5]=&s; 

因为他们两个return相同的输出。

#include <stdio.h>
int main()
{
        int s[5]={10,1,2,3,4};
        int (*p)[10]=s;
        printf("%d\n",*p);
        printf("%d\n",**p);
        printf("%d\n",&s);
        
        printf("\n");

        int (*o)[5]=&s;
        printf("%d\n",*o);
        printf("%d\n",**o);
        printf("%d",&s);
    
        return 0;
}

这个程序的输出是:

-593812272
10
-593812272

-593812272
10
-593812272

这是无效的:

    int s[5]={10,1,2,3,4};
    int (*p)[10]=s;

因为您正在使用 int * 类型的表达式初始化 int (*)[10] 类型的变量(指向大小为 10 的 int 数组的指针)。这些类型不兼容。

虽然这很好:

    int (*o)[5]=&s;

因为初始化器的类型与变量的类型匹配。

此外,在打印指针值时,您应该使用 %p 格式说明符并将参数转换为 void *。格式说明符与其关联参数不匹配会触发 undefined behavior.

这一行

int (*p)[10]=s;

不正确。由于数组指示符 s 到指向其第一个元素的指针的隐式转换,因此初始值设定项具有类型 int *。而且左手边和右手边的两个指针是不兼容的。所以编译器应该发出一条消息。

这一行

int (*o)[5]=&s;

是正确的。初始化器的类型 int ( * )[5] 与初始化指针 o.

的类型相同

注意,要输出指针值,您必须使用转换说明符%p。否则使用转换说明符 %d 输出指针会调用未定义的行为。

例如,而不是这些调用

printf("%d\n",*o);
//...
printf("%d",&s);

你必须写

printf("%p\n", ( void *)*o);
//...
printf("%p\n", ( void * )&s);

表达式 *o 产生数组 s 的值,该值又被隐式转换为指向其第一个元素的指针。

表达式*o和表达式&s的值相同,因为它是数组占用的内存范围的地址。但它们的类型不同。用作 printf 调用参数的第一个表达式的类型为 int *,而第二个表达式的类型为 int ( * )[5].