首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么我们需要在分配C中函数的返回值之前声明变量数据类型?

为什么我们需要在分配C中函数的返回值之前声明变量数据类型?
EN

Stack Overflow用户
提问于 2021-12-07 10:18:19
回答 3查看 464关注 0票数 1

我对C不熟悉。假设我们有一个函数get_float();它应该返回一个浮点值。但是在C中,我们应该先显式声明一个浮点数类型变量,然后再将浮点数赋值给它。

代码语言:javascript
运行
复制
float number = get_float("what's the number");

我想知道为什么要设计这样的规则。

在赋值函数返回值的情况下,如果我们可以声明一个变量而不声明其数据类型,那么它似乎减少了错误。程序员不需要担心他们声明了与函数返回值不匹配的错误数据类型。

代码语言:javascript
运行
复制
number = get_float("what's the number");
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-12-07 13:02:45

你是对的,强迫程序员为每个变量提供一个类型意味着程序员需要做更多的工作。但这是为了减少出错的可能性,而且在大多数情况下是这样的。

你举了个例子

代码语言:javascript
运行
复制
float number = get_float("what's the number");

你把它比作“更简单”

代码语言:javascript
运行
复制
number = get_float("what's the number");

您还写到:“程序员不必担心他们声明了与函数返回值不匹配的错误数据类型。”

但在这里,您假设程序员可能会犯的唯一错误是为变量选择错误类型。您假设程序员在=的右侧符号上写的表达式总是正确的,所以编译器根据右侧的类型来猜测变量的类型总是正确的。但这不一定是真的。程序员可以犯很多不同的错误。当程序员开始犯错误时,试图猜测程序员的意图可能是一个任意棘手的过程。

例如,假设一个粗心的程序员认为fgets函数返回了它刚刚读取的行的长度。假设这个程序员写

代码语言:javascript
运行
复制
line = fgets(stdin);
if(line == 0)
     printf("empty line\n");
else printf("you typed %d characters\n");

这段代码显然是错误的。但是,如果编译器为程序员的line变量选择了一个类型,那么它所选择的类型将是char *,这将不是程序员所希望的。此外,由于测试if(line == 0)将测试fgets是否返回空指针(这就是指示错误的方式),所以程序似乎几乎可以正常工作。因此,这一行也不会出现编译器警告。行printf("you typed %d characters\n")会打印一个非常奇怪的结果,但根据编译器的不同,它也可能不会生成警告。(一些编译器在尝试使用%d打印指针时发出警告,但有些编译器没有警告。)

强迫程序员像C一样为每个变量显式地选择一个类型,并不是在最短的时间内使程序员容易。从长远来看应该更好。

是的,提前选择每个变量的类型需要做更多的工作,是的,如果编译器能够猜出正确的类型,至少在一定的时间内,可能会更容易。是的,当您忘记声明变量时,或者当您以错误的类型声明变量时,会迫使您返回并解决问题,而编译器可能更容易为您修复它们。

但是底线是,强迫您为每个变量选择一个类型迟早会捕获很多错误。强迫您为每个变量选择一个类型会引入一种有用的冗余形式,就像在人类语言中一样,冗余有助于消除一类重要的错误。

当然,强迫您为每个变量选择一个类型并不是唯一可行的策略。有些成功的语言并不强迫你选择--但C语言根本就不是其中之一。

票数 1
EN

Stack Overflow用户

发布于 2021-12-07 10:25:37

例如,有些语言没有严格的Python类型。使用严格类型语言的原因是,这样可以更容易地知道变量是什么。

例如,在Python中可以有一个函数:

代码语言:javascript
运行
复制
def foo(number): 
    if number == 1:
        return "This is a string"
    else: 
        return 200

此函数将返回两个不同的值和值类型。这意味着必须处理函数调用方的返回值,这可能会造成许多麻烦。

类中的变量也是如此,在Python中,您认为可能分配给一个变量时,您必须反复检查它是否包含您所相信的内容,而在严格类型的语言中,变量的类型总是不同。

在某种程度上,就像在示例中一样,在将变量赋值给float时,会进行类型检查。甚至IDE或编译器也会告诉您,函数可能不返回浮点值,因此不应该编译/运行。

票数 2
EN

Stack Overflow用户

发布于 2021-12-07 16:35:34

name = ...不能以这种方式工作的主要原因是变量的范围。想象一个案例:

代码语言:javascript
运行
复制
int name; // global variable
int main() {
   name = 1;
}

name应该引用全局变量还是新创建的局部变量?

需要区分变量声明(即使类型被自动扣除)和赋值。

这一问题出现在B编程语言中,C语言的grand-pa,C++的grand-grand-pa和其他子类中.

通过添加auto关键字来标记表达式实际上是带有初始化器的声明,解决了这个问题。

代码语言:javascript
运行
复制
auto name = 42;

请注意,B只支持一种类型,即或多或少相当于int的cpu寄存器。

随着C的出现,一种新的类型系统被引入,强制在变量之前放置一个类型来标记声明。

代码语言:javascript
运行
复制
int name = 42;

但是,为了保持现有的B代码,添加了关键字auto和隐式int类型规则。

C++保留C语法,auto作为保留关键字。从C++11中,auto用于声明,从初始化器的类型中自动扣除类型。这一特性有可能被添加到更新的C23标准中。见提案

另一方面,Python采用了另一种方法,即赋值创建一个新变量,但现在开发人员被迫使用globalnonlocal语句来绑定变量的作用域。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70258368

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档