【问题标题】:typedef pointer alias vs define pointer aliastypedef 指针别名与定义指针别名
【发布时间】:2020-11-29 21:21:38
【问题描述】:

当你声明一个指向 int 的指针时:

int *a, b;

a 是指向 int 的指针,而 bint (我从来没有真正理解为什么会发生这种情况,我知道与逗号有关,但我曾经说过星号是分箱的到变量名而不是数据类型)。无论如何,如果你:

#define intptr int*
intptr a, b

结果是一样的。我觉得奇怪的事实是为什么使用typedef 来做同样的事情会改变行为?

typdef int* intptr 
intptr a, b;

在最后一个示例中,我期望 aint*,而 bint。相反,它们都是int*


为了澄清,有以下代码 sn-p 我不明白为什么我没有得到 d 变量的相同警告

#define intptr_def int*

typedef int* intptr_typ;

int main()
{
    int x;

    intptr_def a, b;
    intptr_typ c, d;

    a = &x;
    b = &x;     // Warning assignment to 'int' from 'int *' makes integer from pointer without a cast
    c = &x;
    d = &x;

    return 0;
}

【问题讨论】:

  • typedef 与宏不同。 typedef 为类型提供别名。宏进行文本替换。如果您仔细研究该标准(C11 §6.7 Declarations — 一个长部分),您会看到一个声明有两个部分——指定基本类型的“声明说明符”(int 等,但也没有指针或修饰符的修饰符)数组或函数类型),以及“init-declarator list”,其中包含以逗号分隔的各个声明符列表。声明器包括指针、数组和函数类型的装饰。
  • 尝试在宏中的int* 之间添加一个空格(即#define intptr int *),然后“扩展”声明:它扩展为int *a, b;,这就是您之前所拥有的。
  • @Someprogrammerdude:int* 之间的空间无关紧要——不管它们周围的间距如何,都有两个标记(int*)。
  • 在声明中,指针制造者星号绑定到下一个变量。这意味着int* a, b;int * a, b;int *a, b; 都表示同一个意思:a 是指针。
  • @JonathanLeffler 我知道,我的意思是更容易“看到”扩展宏与第一个声明相同。

标签: c typedef


【解决方案1】:

宏是文本替换,仅此而已。如果你有

#define intptr int*

然后写

intptr a, b;

那么当代码被预处理时,intptr宏被扩展

int* a, b;

处理方式完全一样

int *a, b;

并且只将a声明为一个指针; b 是普通的int

typedef 名称是类型的 别名 - 它不像预处理器宏那样进行文本替换。

typedef int *intptr;

创建intptr 作为int * 的别名(指向int 的指针)。 所以当你写

intptr a, b;

ab 都有类型 intptr (int *)。


C 中的声明具有基本结构

<em>declaration-specifiers declarators</em>

声明说明符包括类型说明符(intfloatchar等)、类型限定符(constvolatile)、存储类说明符(staticauto、@ 987654346@),以及其他一些与函数声明/定义相关的说明符。

declarator 引入了被声明事物的名称,以及有关该事物的数组、指针和函数的信息。比如在声明中

static volatile unsigned int a[10], *p;

声明说明符是static volatile unsigned int,声明符是a[10]*p。每个变量的类型完全由声明说明符和声明符的组合指定。 a 的类型是“static volatile unsigned int 的 10 元素数组”,p 的类型是“指向static volatile unsigned int 的指针”。

这个想法是声明符的结构与代码中表达式的结构相匹配。例如,假设您有一个指向名为 iptrint 的指针,并且您想打印它指向的对象中的值,您可以这样写

printf( "%d\n", *iptr );

表达式*iptr的类型是int,所以声明写成

int *iptr;

你也可以写成

int* iptr;

int*iptr;

甚至

int      *      iptr;

所有都将被解释为

int (*iptr);

空格没有任何区别 - * 始终是声明符的一部分,而不是声明说明符。声明符可以变得任意复杂 - 对于任何声明说明符序列T,您可以拥有

T x;          // x is an object of type T
T a[N];       // a is an array of T
T *p;         // p is a pointer to T
T f();        // f is a function returning T

T *a[N];      // a is an array of pointer to T
T (*p)[N];    // p is a pointer to an array of T
T *f();       // f is a function returning pointer to T
T (*p)();     // p is a pointer to a function returning T

T *(*a[N])(); // a is an array of pointers to functions
              // returning pointer to T

这只是触及表面而已。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 2021-06-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多