【问题标题】:Does C have an equivalent to var?C是否有等价于var?
【发布时间】:2021-08-04 22:39:41
【问题描述】:

我想为程序设置一个具有任何值的变量。我能做的最好的事情是使用var,但C 中不存在var 关键字。

我试过这段代码:

#include <stdio.h>

int main() {
    var a = 2;
    puts(a);
}

然后得到这些错误:

var.c:4:5: error: use of undeclared identifier 'var'
    var a = 2;
    ^
var.c:5:10: error: use of undeclared identifier 'a'
    puts(a);
         ^

如果不是var,那么它在 C 中的等价物是什么?

【问题讨论】:

  • 不,没有等价物。但是对于特定的问题可能会有特定的解决方案。
  • C 是严格类型的,因此您需要明确定义具有类型的变量。不管它值多少钱,在 C++ 中,auto 关键字可以执行类型推断,但 C++ 与 C 不同。
  • 当您说“对于程序而言具有任何值的变量”时,您可能不应该以这种方式在 C 中使用变量。您可以使用 C-String 来存储您的原始数据并自行创建解析逻辑,否则您所建议的称为动态类型,这在 C 中是不允许的。
  • 当您学习一门新语言时,您就是在学习一门新语言。不要为所有东西寻找等价物。切换语言时,您经常需要重新考虑一切。
  • @Louis-JacobLebel 道歉;您正在评论我删除的评论。但是真的吗?如果您使用 C++,您将使用 std::ostream 对象 (cout),其中将调用适当的 operator&lt;&lt; 重载。你真的把问题复杂化了。是的,您正在直接回答问题;它也不是惯用的,var 很少是合适的解决方案。在 C 或 C++ 中。不过同意 - 让我们现在停下来!

标签: c variables var equivalent


【解决方案1】:

正如其他人已经提到的,归根结底,您需要知道变量的类型才能对它们进行处理。

除了void * 指针之外,您还可以将所有内容视为 c 字符串nul-终止的字符缓冲区),然后使用任何 C99 @ 987654326@ 系列函数(float*signed*unsigned*)按需将它们转换为所需的类型。

例如,以下将 a 声明为 c 字符串并输出其 floatlong intunsigned long 表示形式:

char *a = "-2.3";
printf( "float: %f\n", strtof(a, NULL) );
printf( "long: %ld\n", strtol(a, NULL, 10) );
printf( "unsigned long: %lu\n", strtoul(a, NULL, 10) );

输出:

float: -2.300000
long: -2
unsigned long: 4294967294

你可以用这些函数做更多花哨的事情(甚至用void *指针做更多的事情),但它们都不能完全回答你的问题,因为你所问的不是C语言直接支持的。

这两个建议都违背了语言的本质。如果你要使用 C,只需学习和使用支持的类型(或定义你自己的,这也很好支持)。

【讨论】:

    【解决方案2】:

    C 是静态类型的。这意味着所有变量都具有特定类型,并且所有函数参数和返回值都具有特定类型。此外,这意味着在分配变量、传递参数或返回值时,该值必须与指定的类型匹配或在语言规则内兼容/转换为该类型。

    这可能看起来不方便,但 C 是一种系统级语言,能够直接与内存和 I/O 有效交互,并且在系统级语言中强类型是必不可少的。有大量与支持弱类型语言相关的代码;在 C 中,它只是一个适当且固定大小的内存位置。

    在您的示例中,变量中有一个整数值 2,但您想使用 puts() 打印一个字符串,该字符串需要一个引用 NUL 终止字符串的 char* 参数。解决此问题的惯用 C 方法是使用将生成整数值的字符串表示的函数。因为 C 不会“神奇地”为您执行转换,所以它有一个库来处理最常见的转换和表示要求。在这种情况下:

    #include <stdio.h>
    
    int main() 
    {
        int a = 2;
        printf( "%d\n", a ) ;
    }
    

    在这种情况下,printf() 使用 %d 格式说明符将整数 2 表示为字符串 "2",后跟换行符。字符串“2”是代码为0x32 或十进制50(假设为ASCII 编码)的字符。

    如果你仍然认为你需要一个变体,(因为在示例中很明显它根本没有必要),然后提出一个新问题,并提供一个你试图解决的问题的更具体示例 - 你无疑会得到一个显示如何在 C 中解决问题的答案 - 并非所有解决方案都像这样简单。

    【讨论】:

    • 我猜你的意思是'静态类型'
    • @tstanisl 仔细想想,是的。会修复的。
    【解决方案3】:

    如果你可以使用指针,你可以使用void *

    #include <stdio.h>
    
    int main() {
     char *s = "abc";
     void *a = s;
     puts(a);
    
     return 0;
    }
    

    【讨论】:

    • 谢谢。从未听说过void *,所以我会调查一下。
    • OP 似乎期望编译器可以推断类型并使用某种类型特定的功能。这样如果a 指向int,那么puts(a); 将把它打印为一个数字。这显然是行不通的。
    • 是的,所有变量都有一个内存位置,所以从技术上讲,您可以使用指针来存储任何类型。但是,这样做可能会使类型解析的过程进一步复杂化。无论如何,您最终都需要转换您的类型,并且要可靠地做到这一点,您需要了解 supposed 的类型是什么。因此,我强烈反对将这种做法作为在 C 中创建“一刀切”的一种方式。
    • 另外值得注意的是,void * 在技术上是一个函数指针。在给定的系统上,所有指针在 C 中都具有相同的大小。因此,所指向的地址是否包含函数、intchar 等都没关系。但是,要可靠地使用您的数据,您'将需要知道所指向的类型。所以这并不能真正解决任何问题。如果您知道正确的类型,只需使用它即可避免添加类型歧义的麻烦。
    • @StackOverflow :一定要看看它,但我看不出如何,这个答案并没有解释它是如何解决你的问题的。
    【解决方案4】:

    用 C 编写的脚本语言设法为其变量实现这一点。但是,它相当复杂。

    C 需要知道事物的大小,以便正确地将它们放入内存中。变量必须始终是已知类型和大小。

    为了有一个未知类型的变量,你需要创建一个类似这样的结构(在我的脑海中,未经测试,但请参阅https://github.com/zlynx/type-union-test):

    struct var {
        enum {
            INT,
            OBJ,
            DOUBLE,
        };
        union {
            long i;
            void* p;
            double d;
        };
    };
    

    然后函数对所有内容进行操作。实现 OBJ 很有趣,因为您需要更多的结构来定义它是数组还是另一个 var 等。

    无论如何。如果您希望在 C 中进行编程更容易,那么不要尝试这个。预先确定你的变量是什么。

    【讨论】:

    • 谢谢。我想这是唯一的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-31
    • 1970-01-01
    • 1970-01-01
    • 2013-06-24
    • 2011-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多