-3

我知道引用注册变量的地址会导致编译错误。

int main()
{
    register int i = 10;
    int *a = &i;
    printf("%d", *a);
    getchar();
    return 0;
}

正如预期的那样,gcc由于引用了已注册变量的地址,因此在使用时会出现编译器错误i

那么下面的代码,做了类似的事情,怎么会没有错误呢?

#include<stdio.h>
int *NEXT(register int i)
{
    int *ipt;
    ipt = &i;
    ipt++;
    return ipt;
}
main ()
{
    int j=2;
    printf("%d",(NEXT(j)));
}

编辑:我的 gcc 版本在

i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (基于 Apple Inc. build 5658) (LLVM build 2335.15.00) 版权所有 (C) 2007 Free Software Foundation, Inc. 这是免费软件;查看复制条件的来源。没有保修;甚至不考虑适销性或特定用途的适用性。

4

3 回答 3

9

如果您的报告是准确的,这可能是由于编译器中的错误,或者可能是编译器不符合标准 C 的许可编译模式。

根据 C 2011 5.1.1.3,C 实现必须在违反约束时产生诊断。根据 6.5.3.2,一个约束是 的操作数&不能用寄存器声明。因此,在这种情况下,符合标准的编译器不能随意忽略错误;它必须产生诊断。

于 2013-06-17T19:42:21.043 回答
4
ipt = &i;

您正在获取register对象的地址。编译器必须发出警告,并且可以在需要时停止编译。这实际上意味着如果您的编译器不发出警告,则编译器不能假装是符合标准的 C 编译器(C99,5.1.1.3p1)。

除此之外:

printf("%d",(NEXT(j)));

d转换说明符需要 aint但您传递的是int *.

于 2013-06-17T19:23:01.563 回答
-1

编译器可以自由地忽略任何寄存器指令,但获取这样一个变量的地址仍然是非法的。

我敢肯定,将寄存器变量作为函数参数传递将在所有情况下被忽略,除非函数是inlined,因为堆栈必须由函数参数填充:以及一个宽容的编译器,例如你的编译器重新使用;将发出它的地址。

我想知道这种行为是否存在standard。我会赞成肯定知道的专家给出的任何答案。

于 2013-06-17T19:22:55.213 回答