声明的区别和范围?

时间:2015-07-20 10:37:48

标签: c

问题Declaration difference?有人问到

之间有什么区别
int i;

for (i=0; i<100; i++) {
    //some loop....
}

for (int i=0; i<100; i++) {
    //some loop....
}

答案很明确;第二个是C99,i的范围仅限于循环。我没有C99所以我无法测试,因此问一个问题:在下列情况下解决方案是什么:

int i = 32;

for (int i=i; i<100; i++) {
    // some loop
}

“新”i是否会使用“旧”i进行初始化?或者旧的i已经无法访问,因为已经宣布了新的i

4 个答案:

答案 0 :(得分:10)

在这个for循环语句中

int i = 32;

for (int i = i; i < 100; i++) {
    // some loop
}
在for语句中声明的

变量i具有不确定的值。问题是,只要定义了一个声明符(在这种情况下它由标识符i组成),它就会在给定的作用域中隐藏一个具有相同名称的实体。所以在这个宣言中

int i = i;

变量i指的是=的右侧。

另一个类似的例子。我们假设你有一个typedef。

typedef int Int;

您可以在定义后写作

Int Int;

在这种情况下,类型为Int的对象的名称Int隐藏了typedef定义,您可能还没有编写

Int Another_Int;

因为编译器会发出错误。

根据C标准(6.2.1标识符范围)

  

4 ...如果声明者或声明的声明的类型说明符   标识符出现在块内或参数列表中   函数定义中的声明,标识符有块作用域,   它终止于相关块的末尾。

更清楚的是在C ++标准(3.3.2声明点)中写的

  

1名称的声明点紧随其后   完整的声明者(第8条)和初始化者(如果有的话),   除非如下所述。 [例如:

int x = 12;
{ int x = x; }
  

这里第二个x用它自己的(不确定的)值初始化。    - 例子]

请在此代码段中考虑

int i = 10;

{
    int i[i];
}

在复合语句中,声明数组int i[10];,外部变量i用作数组大小,因为内部变量i仅在其声明符完成时才会声明。

答案 1 :(得分:8)

参见C11 6.8.5.3“如果子句-1是一个声明,它声明的任何标识符的范围是声明的剩余部分和整个循环,包括其他两个表达式”。

第二个i是指定义的i,而不是旧的。{/ p>

整个事情是 UB ,因为你使用的是i(在循环中定义的i)的值而没有先前的赋值(或初始化)。< / p>

使用工作(但不同)示例编辑

您仍然可以通过使用指针

来使用旧值
int i = 42;
int *old_i = &i;
for (int i = *old_i; i < 50; i++) printf("%d ", i);

答案 2 :(得分:5)

不,在任何情况下都像

int i=i;

是一个坏主意,因为第二个i与第一个int tmp=i, i=tmp; 是同一个对象,但仍未初始化。

如果你坚持要做一些像

这样的事情
<country>United Kingdom</country>
<countryCode>UK</countryCode>
<region>Bristol</region>
<ip>xx.xx.xx.x</ip>
<ISP>VodafoneM</ISP>

获得你想要的效果。

答案 3 :(得分:2)

感谢Jens Gustedt,我做了一些研究,这是我发现的:以下代码:

NewNewsAdapter adapters = new NewNewsAdapter(getActivity().getApplicationContext(), R.layout.newnews, newsList);
listedView.setAdapter(adapters);
adapters.notifyDataSetChanged();

produce this assembly与gcc 5.2:

#include<stdio.h>
int main()
{
    int i = 32;

    for (int i=i; i<50; i++) {
        printf("Hello World %d", i); // <-- this is the new i, the other one is not accessible here
    }
    return 0;
}

用于循环的变量是.LC0: .string "Hello World %d" main: push rbp mov rbp, rsp sub rsp, 16 mov DWORD PTR [rbp-8], 32 .L3: cmp DWORD PTR [rbp-4], 49 jg .L2 mov eax, DWORD PTR [rbp-4] mov esi, eax mov edi, OFFSET FLAT:.LC0 mov eax, 0 call printf add DWORD PTR [rbp-4], 1 jmp .L3 .L2: mov eax, 0 leave ret ,它没有被初始化,可以是任何东西。所以它确实是一个UB。