C函数是否保证有固定的内存地址?

C函数是否保证有固定的内存地址?,c,pointers,function-pointers,C,Pointers,Function Pointers,如果我存储一个指向某个函数的指针,然后在程序执行过程中的某个时间点,将它与同一个函数的地址进行比较,这两个地址是否保证相等 例如 在上面的代码中,断言总是保证成功吗?是否存在函数地址可以更改的情况?根据6.5.9: 两个指针比较相等当且仅当两个指针都是空指针,都是指向同一个对象的指针(包括指向对象的指针和开头的子对象)或函数,都是指向同一数组对象最后一个元素的指针,或者一个指针指向一个数组对象的末尾,另一个指针指向另一个数组对象的开头,该数组对象恰好紧跟在地址空间中的第一个数组对象之后 (为强调

如果我存储一个指向某个函数的指针,然后在程序执行过程中的某个时间点,将它与同一个函数的地址进行比较,这两个地址是否保证相等

例如

在上面的代码中,断言总是保证成功吗?是否存在函数地址可以更改的情况?

根据6.5.9:

两个指针比较相等当且仅当两个指针都是空指针,都是指向同一个对象的指针(包括指向对象的指针和开头的子对象)或函数,都是指向同一数组对象最后一个元素的指针,或者一个指针指向一个数组对象的末尾,另一个指针指向另一个数组对象的开头,该数组对象恰好紧跟在地址空间中的第一个数组对象之后


(为强调起见,增加了黑体。)

函数的地址永远不会改变。许多程序都是围绕回调的概念构建的,如果函数的地址发生变化,回调就不起作用

假设某个函数的位置发生了变化(例如通过自修改程序),那么对该函数的所有调用都将导致segfault或任何方式的未定义行为。编辑:澄清-函数符号类似于指针,如果您
释放了指针指向的内存,这不会使实际指针变量归零,它仍将指向那里,就像您的函数调用仍将指向移动函数的旧位置一样

但是,自修改程序是非常大的例外,在这些日子里,二进制文件的代码部分是写保护的,这非常非常困难

int foo(void){return 0;}
int (*foo_p)(void) = &foo;

assert(foo_p == &foo);