【问题标题】:What is the difference between int (*p)[10]=s and int (*o)[5]=&s?int (*p)[10]=s 和 int (*o)[5]=&s 有什么区别?
【发布时间】:2021-12-12 21:54:23
【问题描述】:

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

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

int (*p)[10]=s; 

但为什么更喜欢

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

因为它们都返回相同的输出。

#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 (*p)[10]=s; 生成一个警告:`警告:不兼容的指针类型初始化'int (*)[5]' 使用'int [5]' 类型的表达式;用 & [-Wincompatible-pointer-types]`获取地址

标签: arrays c pointers printf pointer-to-array


【解决方案1】:

这是无效的:

    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

【讨论】:

    【解决方案2】:

    这一行

    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 和表达式&amp;s 的值相同,因为它是数组占用的内存范围的地址。但它们的类型不同。用作printf 调用参数的第一个表达式的类型为int *,而第二个表达式的类型为int ( * )[5]

    【讨论】:

      猜你喜欢
      • 2021-12-30
      • 2019-08-14
      • 1970-01-01
      • 2019-11-06
      • 2016-01-23
      • 2021-01-05
      • 2018-11-08
      • 2013-08-14
      • 2010-12-14
      相关资源
      最近更新 更多