C 有等价于 var 的东西吗?
Does C have an equivalent to var?
我想为程序设置一个任意值的变量。我能做的最好的事情就是使用 var
,但是 var
关键字在 C 中不存在。
我试过这段代码:
#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 需要知道事物的大小,以便它可以将它们正确地放入内存中。变量必须始终是已知类型和大小。
为了拥有一个未知类型的变量,您需要创建一个类似这样的结构(超出我的想象,未经测试,但请参阅 https://github.com/zlynx/type-union-test):
struct var {
enum {
INT,
OBJ,
DOUBLE,
};
union {
long i;
void* p;
double d;
};
};
然后是对所有东西进行操作的函数。实现 OBJ 变得很有趣,因为您需要更多的结构来定义它是数组还是另一个 var 等等。
总之。如果您希望使用 C 更轻松 进行编程,那么请不要尝试此操作。预先决定你的变量是什么。
能用指针就用void *
:
#include <stdio.h>
int main() {
char *s = "abc";
void *a = s;
puts(a);
return 0;
}
C 是静态类型的。这意味着所有变量都有特定类型,所有函数参数和 return 值都有特定类型。此外,这意味着在分配变量、传递参数或 returning 值时,该值必须匹配指定的类型或 compatible/convertible 符合语言规则的该类型。
这可能看起来很不方便,但 C 是一种系统级语言,能够直接与内存交互,并且 I/O 高效,在系统级语言中,强类型是必不可少的。有大量与支持弱类型语言相关的代码;在 C 中,它只是一个适当且固定大小的内存位置。
在您的示例中,您的变量中有一个整数值 2,但您想使用 puts()
打印一个字符串,该字符串需要一个 char*
参数来引用以 NUL 结尾的字符串。解决此问题的惯用 C 方法是使用一个函数来生成整数值的字符串表示形式。因为 C 不会“神奇地”为您执行该转换,所以它有一个库可以处理最常见的转换和表示要求。在这种情况下:
#include <stdio.h>
int main()
{
int a = 2;
printf( "%d\n", a ) ;
}
在这种情况下,printf()
使用 %d
格式说明符将整数 2 表示为字符串 "2"
,后跟换行符。字符串“2”是一个代码为 0x32
或 50 十进制(假设 ASCII 编码)的字符。
如果你仍然认为你需要一个变体,(因为在这个例子中很明显它根本没有必要),然后用你试图解决的问题的更具体的例子提出一个新问题 - 你不会有疑问得到答案,说明如何用 C 语言解决问题 - 并非所有解决方案都像这样简单。
正如其他人已经提到的,归根结底,您需要知道变量的类型才能对其进行处理。
除了 void *
指针之外,您还可以 将所有内容都视为 C 字符串 (nul
-终止的字符缓冲区),然后使用任何C99 strto*
函数族 (float*, signed*, unsigned*) 按需将它们转换为预期类型。
例如,下面将 a
声明为 c 字符串并输出其 float
、long int
和 unsigned 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,只要学习和使用支持的类型(或者定义你自己的,也很好支持)。
我想为程序设置一个任意值的变量。我能做的最好的事情就是使用 var
,但是 var
关键字在 C 中不存在。
我试过这段代码:
#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 需要知道事物的大小,以便它可以将它们正确地放入内存中。变量必须始终是已知类型和大小。
为了拥有一个未知类型的变量,您需要创建一个类似这样的结构(超出我的想象,未经测试,但请参阅 https://github.com/zlynx/type-union-test):
struct var {
enum {
INT,
OBJ,
DOUBLE,
};
union {
long i;
void* p;
double d;
};
};
然后是对所有东西进行操作的函数。实现 OBJ 变得很有趣,因为您需要更多的结构来定义它是数组还是另一个 var 等等。
总之。如果您希望使用 C 更轻松 进行编程,那么请不要尝试此操作。预先决定你的变量是什么。
能用指针就用void *
:
#include <stdio.h>
int main() {
char *s = "abc";
void *a = s;
puts(a);
return 0;
}
C 是静态类型的。这意味着所有变量都有特定类型,所有函数参数和 return 值都有特定类型。此外,这意味着在分配变量、传递参数或 returning 值时,该值必须匹配指定的类型或 compatible/convertible 符合语言规则的该类型。
这可能看起来很不方便,但 C 是一种系统级语言,能够直接与内存交互,并且 I/O 高效,在系统级语言中,强类型是必不可少的。有大量与支持弱类型语言相关的代码;在 C 中,它只是一个适当且固定大小的内存位置。
在您的示例中,您的变量中有一个整数值 2,但您想使用 puts()
打印一个字符串,该字符串需要一个 char*
参数来引用以 NUL 结尾的字符串。解决此问题的惯用 C 方法是使用一个函数来生成整数值的字符串表示形式。因为 C 不会“神奇地”为您执行该转换,所以它有一个库可以处理最常见的转换和表示要求。在这种情况下:
#include <stdio.h>
int main()
{
int a = 2;
printf( "%d\n", a ) ;
}
在这种情况下,printf()
使用 %d
格式说明符将整数 2 表示为字符串 "2"
,后跟换行符。字符串“2”是一个代码为 0x32
或 50 十进制(假设 ASCII 编码)的字符。
如果你仍然认为你需要一个变体,(因为在这个例子中很明显它根本没有必要),然后用你试图解决的问题的更具体的例子提出一个新问题 - 你不会有疑问得到答案,说明如何用 C 语言解决问题 - 并非所有解决方案都像这样简单。
正如其他人已经提到的,归根结底,您需要知道变量的类型才能对其进行处理。
除了 void *
指针之外,您还可以 将所有内容都视为 C 字符串 (nul
-终止的字符缓冲区),然后使用任何C99 strto*
函数族 (float*, signed*, unsigned*) 按需将它们转换为预期类型。
例如,下面将 a
声明为 c 字符串并输出其 float
、long int
和 unsigned 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,只要学习和使用支持的类型(或者定义你自己的,也很好支持)。