未定义的变量和编译器优化

时间:2016-12-11 02:11:45

标签: c compiler-construction undefined

我有一个关于未定义变量的问题以及下面显示的剪切代码:

func_1()之后---它会将A推入堆栈并将该内存的值设置为40,然后将A弹出堆栈。

func_2()之后---它会再次将A推入堆栈并继承之前设置的值,打印输出值将为40。

void func_1()
{ int A = 40;}

void func_2()
{ int A; printf("%d/n",A);}

void main (void)
{
  func_1();
  func_2();
}

如果我们将A中的名称func_2()更改为B来测试堆栈的使用,并在其中加入额外的代码来测试命名变量池的使用: / p>

int A; printf("%d\n", A);

在我的计算机上,它显示B为40,A为0.

我想知道的是,如果编译器有一个命名变量池,它重用它来帮助它优化编译代码(?),那为什么我在A得到0? 编译器何时使用池?

我的问题是基于这张幻灯片: http://www.slideshare.net/olvemaudal/deep-c/131-I_am_now_going_to

2 个答案:

答案 0 :(得分:3)

函数A中的变量func_2();很可能被分配到保存值40的相同堆栈位置(在func_1()中)。因为,你没有初始化func_2()中的变量,它将使用它在内存中的随机值打印变量40(因为它从未被重写)。它类似于用户释放指针时的情况,并声称他们之后也能看到它的竞争,尽管他们可能会或不会看到它是未定义的行为。不用说,你不应该依赖这种行为!

我做了一个简单的测试,证明它与名字无关:

void func_1()
{ 
    int A = 40; 
    int B = 10;
    printf("Memory A = %p Memory B = %p\n",&A, &B);
}

void func_2()
{ int B; printf("B = %d Memory B = %p\n",B, &B);}

void main (void)
{
  func_1();

  func_2();
  printf("\n");
}

<强>输出

Memory A = 0x7fff58f86b5c Memory B = 0x7fff58f86b58
B = 40 Memory B = 0x7fff58f86b5c

正如您所看到的B = 10 func_1() func_2()中的A打印值为40,为什么?如果检查func_1()中变量B的内存地址是0x7fff58f86b5c func_2()中变量func loadContact(snap : FIRDataSnapshot) -> Contact { let key = snap.key let contact = (snap.value) as? NSDictionary let c1 = Contact( id: (contact?["id"] as? String)!, firebasekey: key, first_name: (contact?["First Name"] as? String)!, middle_name: (contact?["Middle Name"] as? String)!, last_name: (contact?["Last Name"] as? String)!, suffix: (contact?["Suffix"] as? String)!, company: (contact?["Company"] as? String)!, phone_labe1: (contact?["Phone Label 1"] as? String)!, phone1: (contact?["Phone 1"] as? String)!, phone_label2: (contact?["Phone Label 2"] as? String)!, phone2: (contact?["Phone 2"] as? String)!, email_label1: (contact?["Email Label 1"] as? String)!, email1: (contact?["Email 1"] as? String)!, email_label2: (contact?["Email Label 2"] as? String)!, email2: (contact?["Email 2"] as? String)!, social: (contact?["Social Security Number"] as? String)!, dob: (contact?["Date of Birth"] as? String)!, street: (contact?["Street"] as? String)!, city: (contact?["City"] as? String)!, zip: (contact?["ZIP and Postal Code"] as? String)!, state: (contact?["State and Province"] as? String)!, reg_number: (contact?["Reg Num"] as? String)!, stable_reg_number: (contact?["Stable Reg Num"] as? String)!, emergency_contact: (contact?["Emergency Contact"] as? String)!, emergency_phone: (contact?["Emergency Phone"] as? String)!, drivers_license: (contact?["Driver's License Num"] as? String)!, insurance_carrier: (contact?["Insurance Carrier"] as? String)!, details: (contact?["Details"] as? String)!, insurance_exp: (contact?["Insurance Expiration Date"] as? String)!, insurance_group: (contact?["Insurance Group Num"] as? String)!, insurance_member: (contact?["Insurnace Member Num"] as? String)!, // spelled wrong in database job_title: (contact?["Job Title"] as? String)!, date_modified: (contact?["Modified"] as? String)!, keywords: [], notes: [] ) return c1; } 占用的内存地址相同。

答案 1 :(得分:3)

幻灯片中的人物扮演着一个发明一个想法的白痴,这个想法似乎解释了他不理解的行为。没有命名变量池。

此代码的行为未定义且无法依赖。如果它恰好在运行时表现为打印值40,那只是实现的意外。

相关问题