将局部变量的地址分配给C中的全局指针?

将局部变量的地址分配给C中的全局指针?,c,pointers,C,Pointers,我是C语言的新手。如果我将局部变量的地址分配给全局指针,会发生什么?像 #include <stdio.h> void func(); int *ptr; int main() { func(); } void func() { int i = 0; ptr = &i; } #包括 void func(); int*ptr; int main() { func(); } void func() { int i=0; ptr=&i; } 将

我是C语言的新手。如果我将局部变量的地址分配给全局指针,会发生什么?像

#include <stdio.h>

void func();
int *ptr;

int main()
{
    func();
}

void func()
{
    int i = 0;
    ptr = &i;
} 
#包括
void func();
int*ptr;
int main()
{
func();
}
void func()
{
int i=0;
ptr=&i;
} 

将局部变量的地址分配给全局指针是正确的方法吗?

它只是执行您所做的操作,没有任何错误,只是它可能不是您想要的

因此,它只是将
i
的地址分配给
ptr
的分配点。离开
func
时,此指针无效

注意此行为已完全定义:已定义分配给全局变量的位置处的
i
的地址,因此您可以分配它。当您离开函数
func
后尝试取消对变量的引用时,此问题才会出现。只要只在
func
中使用全局变量,这就没有问题(除了全局变量实际上没有意义)

此时,该变量不再存在。在这种情况下,很可能会出现segfault,或者至少会出现一些奇怪的数字(因为您已经用一些其他值覆盖了旧堆栈帧)


作为旁注:我指的是堆叠框架。您可以在大多数编译器上尝试此代码(无需优化!)

因为从
main()
调用
f1
f2
时,变量
i
将具有相同的地址

通过优化,对
f2()
的调用将得到优化


仍然:这是未定义的行为,不能执行。

它只是做你所做的事情,没有什么错,只是它可能不是你想要的

因此,它只是将
i
的地址分配给
ptr
的分配点。离开
func
时,此指针无效

注意此行为已完全定义:已定义分配给全局变量的位置处的
i
的地址,因此您可以分配它。当您离开函数
func
后尝试取消对变量的引用时,此问题才会出现。只要只在
func
中使用全局变量,这就没有问题(除了全局变量实际上没有意义)

此时,该变量不再存在。在这种情况下,很可能会出现segfault,或者至少会出现一些奇怪的数字(因为您已经用一些其他值覆盖了旧堆栈帧)


作为旁注:我指的是堆叠框架。您可以在大多数编译器上尝试此代码(无需优化!)

因为从
main()
调用
f1
f2
时,变量
i
将具有相同的地址

通过优化,对
f2()
的调用将得到优化


仍然:这是未定义的行为,不能执行。

您的语法正确,但局部变量不再存在,因为它属于函数调用的代码块的范围。要解决此问题,一个选项是将局部变量设为静态:

#include <stdio.h>

void func();
int *ptr;

int main()
{
    func();
}

void func()
{
    static int i = 0;
    ptr = &i;
}
#包括
void func();
int*ptr;
int main()
{
func();
}
void func()
{
静态int i=0;
ptr=&i;
}
另一个选项是在函数调用中分配新内存,将全局指针设置为新分配内存的地址:

#include <stdio.h>

void func();
int *ptr = NULL;

int main()
{
    func();
}

void func()
{
    if(ptr != NULL)
        free(ptr);
    int *i = (int *)malloc(sizeof(int));
    ptr = i;
}
#包括
void func();
int*ptr=NULL;
int main()
{
func();
}
void func()
{
如果(ptr!=NULL)
免费(ptr);
int*i=(int*)malloc(sizeof(int));
ptr=i;
}

语法正确,但局部变量不再存在,因为它属于函数调用的代码块范围。要解决此问题,一个选项是将局部变量设为静态:

#include <stdio.h>

void func();
int *ptr;

int main()
{
    func();
}

void func()
{
    static int i = 0;
    ptr = &i;
}
#包括
void func();
int*ptr;
int main()
{
func();
}
void func()
{
静态int i=0;
ptr=&i;
}
另一个选项是在函数调用中分配新内存,将全局指针设置为新分配内存的地址:

#include <stdio.h>

void func();
int *ptr = NULL;

int main()
{
    func();
}

void func()
{
    if(ptr != NULL)
        free(ptr);
    int *i = (int *)malloc(sizeof(int));
    ptr = i;
}
#包括
void func();
int*ptr=NULL;
int main()
{
func();
}
void func()
{
如果(ptr!=NULL)
免费(ptr);
int*i=(int*)malloc(sizeof(int));
ptr=i;
}

您得到的是语法正确的,并且编写的代码在语义上是有效的(但是由于从来没有使用过
ptr
,所以它有点毫无意义)

如果您访问
ptr
,当它包含超出范围的指针时,您会得到未定义的行为

但是,请考虑一个稍微大一些的代码片段。这里,设置

ptr
的代码调用使用
ptr
的函数,并且
ptr
指向的变量仍然是定义的,因此使用指针没有问题

#include <stdio.h>

void func(void);
void use_pointer(void);

int *ptr;

int main(void)
{
    func();       // NB: argument not allowed with prototype!
    int i = 20;
    printf("%s: A %d\n", __func__, i);
    ptr = &i;
    use_pointer();
    printf("%s: B %d\n", __func__, i);
}

void func(void)
{
    int i = 0;
    printf("%s: A %d\n", __func__, i);
    ptr = &i;
    use_pointer();
    printf("%s: B %d\n", __func__, i);
}

void use_pointer(void)
{
    printf("ptr = %p; *ptr = %d\n", (void *)ptr, *ptr);
    *ptr = 42;
}

您得到的是语法正确的,并且编写的代码在语义上是有效的(但是因为从来没有使用过
ptr
,所以它有点毫无意义)

如果您访问
ptr
,当它包含超出范围的指针时,您会得到未定义的行为

但是,请考虑一个稍微大一些的代码片段。这里,设置

ptr
的代码调用使用
ptr
的函数,并且
ptr
指向的变量仍然是定义的,因此使用指针没有问题

#include <stdio.h>

void func(void);
void use_pointer(void);

int *ptr;

int main(void)
{
    func();       // NB: argument not allowed with prototype!
    int i = 20;
    printf("%s: A %d\n", __func__, i);
    ptr = &i;
    use_pointer();
    printf("%s: B %d\n", __func__, i);
}

void func(void)
{
    int i = 0;
    printf("%s: A %d\n", __func__, i);
    ptr = &i;
    use_pointer();
    printf("%s: B %d\n", __func__, i);
}

void use_pointer(void)
{
    printf("ptr = %p; *ptr = %d\n", (void *)ptr, *ptr);
    *ptr = 42;
}

调用表达式的未定义行为与被调用函数的类型不匹配。您的赋值是正确的;但是,离开
func
后,变量
i
不再存在,从此以后您就有了未定义的行为。查找“悬空指针”未定义的行为,查找与被调用函数类型不匹配的调用表达式。