C 为什么赋值保持在范围之外,而声明不保持

C 为什么赋值保持在范围之外,而声明不保持,c,C,我想知道是否有人能解释为什么在C中会发生以下行为。在下面的例子中,我声明了一个变量在作用域外,然后在一个内部作用域内(如果…或者其他),赋值完成,然后赋值持续超过该内部作用域 int main(int argc, char *argv[]) { char *str; if (argc == 2) { str = "Two"; } else { str = "Not two"; }

我想知道是否有人能解释为什么在C中会发生以下行为。在下面的例子中,我声明了一个变量在作用域外,然后在一个内部作用域内(如果
或者
其他
),赋值完成,然后赋值持续超过该内部作用域

int main(int argc, char *argv[])
{
    char *str;
    if (argc == 2) {
        str = "Two";
    }
    else {
        str = "Not two";
    }
    my_print(str);
}
不是两个

但是对于具有初始化的声明,它并不超出范围

int main(int argc, char *argv[])
{
    if (argc == 2) {
        char* str = "Two";
    }
    else {
        char* str = "Not two";
    }
    my_print(str);
}
ix.c:在函数“main”中:
ix.c:15:9:错误:“char”之前应为表达式
char*str=“不是两个”
.........^~~~ ix.c:16:14:错误:“str”未声明(首次在此函数中使用)
我的指纹(str)
^~~


有人能解释一下情况吗?例如,为什么上面两个不能产生相同的输出?

在第二个示例中,它不仅仅是一个“带初始化的声明”:您在
if
分支和
else
分支的内部范围内声明和初始化


int main(int argc, char *argv[])
{
    // SCOPE A
    if (argc == 2) {
        // SCOPE B
        char* str = "Two";
    }
    else {
        // SCOPE C
        char* str = "Not two";
    }
    my_print(str);
}
所以你有三个不同的范围。您试图使用的变量在您使用的范围内不存在。要使代码不会引发编译时错误,应使用以下代码:


int main(int argc, char *argv[])
{
    // SCOPE A
    if (argc == 2) {
        // SCOPE B
        char* str = "Two";
        my_print(str);
    }
    else {
        // SCOPE C
        char* str = "Not two";
        my_print(str);
    }
}

如前所述:“变量在其声明的范围内是局部的”

变量的每个标识符的范围都由其声明的位置决定

此外,if(或if else)语句的每个关联子语句都形成自己的块,其作用域是selection语句作用域的严格子集

所以在这个节目里,

int main(int argc, char *argv[])
{
    char *str;
    if (argc == 2) {
        str = "Two";
    }
    else {
        str = "Not two";
    }
    my_print(str);
}
int main(int argc, char *argv[])
{
    if (argc == 2) {
        char* str = "Two";
    }
    else {
        char* str = "Not two";
    }
    my_print(str);
}
变量
str
在main的外部范围内声明(并为其分配内存,即定义变量),并且在该块和任何内部子块中可见

字符串文字具有静态存储持续时间。例如,在退出if语句的sub语句块之后

    if (argc == 2) {
        str = "Two";
    }
    my_print(str);
字符串文本处于活动状态,变量
str
中存储的指针是有效指针

在这个节目里

int main(int argc, char *argv[])
{
    char *str;
    if (argc == 2) {
        str = "Two";
    }
    else {
        str = "Not two";
    }
    my_print(str);
}
int main(int argc, char *argv[])
{
    if (argc == 2) {
        char* str = "Two";
    }
    else {
        char* str = "Not two";
    }
    my_print(str);
}
您声明了两个名为
str
的变量,每个变量都有一个块作用域,它是if-else语句的相应子语句的子块

在这些块范围之外,变量
str
不活动且不可见。因此,编译器发出一个错误,即名称
str
未在语句中使用的main的外部范围中声明

    if (argc == 2) {
        str = "Two";
    }
    my_print(str);

我不确定你在找什么。变量是声明它的作用域的局部变量,它包括可能出现在该作用域中的所有其他作用域。只要它在范围内,您就可以在您希望的范围内的任何部分读取或写入它,但不能在范围外。这正是语言的设计方式。在第二个示例中,它被称为块作用域,在C中受支持。在第二个示例中,变量被声明并且只存在于块内。@NateEldredge实际上,这是我想我遗漏的关键点:
变量是在其声明的作用域***
的局部。是的,对象生存期,对象值和控制流都是完全独立的方面。否则,除非嵌套所有条件或使用递归(而有状态逻辑是绝对不可能的),否则您永远无法编写具有复杂逻辑的程序。您是否真的想问为什么赋值会跨块作用域持久化,或者为什么声明不会持久化?