user-0 提问: C语言内的宏变量问题

回复:
user: user-0
content: 引用 29 楼 mymtom 的回复:由于C99支持VLA(variable length array), 如果char voip_exten[ MAX_VOIP_EXTEN]是局部变量，而且不是某结构体的成员，就比较简单了，MAX_VOIP_EXTEN 定义成一个变量，程序启动的时候从数据库给这个变量赋值就就可以了。  #include <stdio.h>  #define MAX_VOIP_EXTEN  256  /* 增加三行就好了 */ int g_max_voip_exten; #undef  MAX_VOIP_EXTEN #define MAX_VOIP_EXTEN  g_max_voip_exten  int foo(void) {     char voip_exten[ MAX_VOIP_EXTEN];      printf("%d\n", (int)sizeof(voip_exten));     return 0; }  int main(int argc, char *argv[]) {      g_max_voip_exten = argc;      foo();      return 0; }   即使在C99中增加了对VLA的支持，但是还是不能初始化VLA,

user: user-1
content: 由于C99支持VLA(variable length array), 如果char voip_exten[ MAX_VOIP_EXTEN]是局部变量，而且不是某结构体的成员，就比较简单了，MAX_VOIP_EXTEN 定义成一个变量，程序启动的时候从数据库给这个变量赋值就就可以了。  #include <stdio.h>  #define MAX_VOIP_EXTEN  256  /* 增加三行就好了 */ int g_max_voip_exten; #undef  MAX_VOIP_EXTEN #define MAX_VOIP_EXTEN  g_max_voip_exten  int foo(void) {     char voip_exten[ MAX_VOIP_EXTEN];      printf("%d\n", (int)sizeof(voip_exten));     return 0; }  int main(int argc, char *argv[]) {      g_max_voip_exten = argc;      foo();      return 0; }

user: user-2
content: 你需要的值大于MAX_VOIP_EXTEN吗？大于就必须改源码，小于还好说

user: user-0
content: 引用 29 楼 mymtom 的回复:由于C99支持VLA(variable length array), 如果char voip_exten[ MAX_VOIP_EXTEN]是局部变量，而且不是某结构体的成员，就比较简单了，MAX_VOIP_EXTEN 定义成一个变量，程序启动的时候从数据库给这个变量赋值就就可以了。  #include <stdio.h>  #define MAX_VOIP_EXTEN  256  /* 增加三行就好了 */ int g_max_voip_exten; #undef  MAX_VOIP_EXTEN #define MAX_VOIP_EXTEN  g_max_voip_exten  int foo(void) {     char voip_exten[ MAX_VOIP_EXTEN];      printf("%d\n", (int)sizeof(voip_exten));     return 0; }  int main(int argc, char *argv[]) {      g_max_voip_exten = argc;      foo();      return 0; }  恩阿，学习了。 听老师这么讲，这个做法好像还是有局限性的

user: user-0
content: 引用 27 楼 zhao4zhong1 的回复:那就只有将源代码改为动态分配。 恩阿。多谢老师。本来是想，在新的支持协议中有取巧的办法解决这个问题

user: user-3
content: 引用 22 楼 BeanJoy 的回复:[quote=引用 20 楼 zhao4zhong1 的回复:] 楼主会代码生成（Code Generation）技术吗？ 从数据库取出值，然后生成代码，然后编译，然后发布。 如果用户那数据库中值修改了，然后再生成新代码，再编译，再发布？ 可行吗？[/quote] 为什么不可行？

user: user-4
content: 引用 20 楼 zhao4zhong1 的回复:楼主会代码生成（Code Generation）技术吗？ 从数据库取出值，然后生成代码，然后编译，然后发布。 如果用户那数据库中值修改了，然后再生成新代码，再编译，再发布？ 可行吗？

user: user-3
content: 那就只有将源代码改为动态分配。

user: user-0
content: 引用 24 楼 BeanJoy 的回复:[quote=引用 23 楼 zhao4zhong1 的回复:] [quote=引用 22 楼 BeanJoy 的回复:] [quote=引用 20 楼 zhao4zhong1 的回复:] 楼主会代码生成（Code Generation）技术吗？ 从数据库取出值，然后生成代码，然后编译，然后发布。 如果用户那数据库中值修改了，然后再生成新代码，再编译，再发布？ 可行吗？[/quote] 为什么不可行？[/quote]  可行是可行。 但是这样不得在客户机器上装编译环境，不得把相应的代码拷到客户机器上，在更改数据库一个值后，还得先编译了再运行，谁能接受？反正我是接受不了。[/quote]  这样子就是我这边再打个临时版本给客户，根本起不到远程修改的效果

user: user-3
content: 如果不想将源代码改为动态分配，别无他法。

user: user-4
content: 引用 23 楼 zhao4zhong1 的回复:[quote=引用 22 楼 BeanJoy 的回复:] [quote=引用 20 楼 zhao4zhong1 的回复:] 楼主会代码生成（Code Generation）技术吗？ 从数据库取出值，然后生成代码，然后编译，然后发布。 如果用户那数据库中值修改了，然后再生成新代码，再编译，再发布？ 可行吗？[/quote] 为什么不可行？[/quote] 可行是可行。 但是这样不得在客户机器上装编译环境，不得把相应的代码拷到客户机器上，在更改数据库一个值后，还得先编译了再运行，谁能接受？反正我是接受不了。

user: user-5
content: 纯C语言是不支持动态数组的. C++也只有支持高版C++标准的可以支持动态数组.  你的问题就是动态数组问题.    宏就是一个编译时的文本替换.  所以不可能实现你的需求.  目前来看, 你只能动态分配 , 别无它法了.

user: user-3
content: 楼主会代码生成（Code Generation）技术吗？

user: user-0
content: 引用 10 楼 xiaohuh421 的回复:宏,  不是常量也不是变量.  只是编译时的文本替换.  你的问题, 只需要动态申请内存即可.  动态数组, 只有C++高版本的标准才支持.  并不是动态问题，是要根据数据库改变宏的值，而使得char aaa[MAX_VOIP_EXTEN]这类（很多）数组依旧可用，而不是全部改用malloc

user: user-6
content: 数据下标要确定，我还以为是寻址时要常量，原来是在说定义数组的时候。

user: user-3
content: 仅供参考//codegen.c // 输入一组字符串，比如 // aa ss ddd dd 33 dd // 然后自动生成一个函数 int A(const char*); // 实现A("aa")返回0  A("ss")返回1 依次类推 #include <stdio.h> int main(int argc,char **argv) {     int i;     if (argc<2) {         printf("%s p1 [p2 ...] [>result.c]\nGenerate code int A(const char *a); 0==A(\"p1\") 1==A(\"p2\") ...",argv[0]);         return 1;     }     //printf("#include <string.h>\n");     printf("int A(const char *a) {\n");     for (i=0;i<argc-1;i++) {         printf("    if (0==strcmp(a,\"%s\")) return %d;\n",argv[i+1],i);     }     printf("    return -1;\n");     printf("}\n");     return 0; } //C:\test\Debug>codegen.exe //codegen.exe p1 [p2 ...] [>result.c] //Generate code int A(const char *a); 0==A("p1") 1==A("p2") ... //C:\test\Debug>codegen.exe aa ss ddd dd 33 dd //int A(const char *a) { //    if (0==strcmp(a,"aa")) return 0; //    if (0==strcmp(a,"ss")) return 1; //    if (0==strcmp(a,"ddd")) return 2; //    if (0==strcmp(a,"dd")) return 3; //    if (0==strcmp(a,"33")) return 4; //    if (0==strcmp(a,"dd")) return 5; //    return -1; //} // //c:\test\Debug>codegen.exe aa ss ddd dd 33 dd >result.c // //c:\test\Debug>type result.c //int A(const char *a) { //    if (0==strcmp(a,"aa")) return 0; //    if (0==strcmp(a,"ss")) return 1; //    if (0==strcmp(a,"ddd")) return 2; //    if (0==strcmp(a,"dd")) return 3; //    if (0==strcmp(a,"33")) return 4; //    if (0==strcmp(a,"dd")) return 5; //    return -1; //} //

user: user-7
content: 引用 3 楼 Code_Fly 的回复:[quote=引用 2 楼 jwj070524 的回复:] 直接是不行，C语言不是动态的。一种折中的办法是，先在代码中用undef编译指令取消这些宏定义，然后重新使用这些被取消的符号变成全局变量，之后写一个从数据库中读出这些变量的函数，在程序初始化阶段给这些全局变量赋值。  那这样子那些宏全部变成全局变量，不能作为数组的大小[/quote]  引用 4 楼 lovesmiles 的回复:[quote=引用 2 楼 jwj070524 的回复:] 直接是不行，C语言不是动态的。一种折中的办法是，先在代码中用undef编译指令取消这些宏定义，然后重新使用这些被取消的符号变成全局变量，之后写一个从数据库中读出这些变量的函数，在程序初始化阶段给这些全局变量赋值。  别胡扯，在C语言里面数组下标不能用变量表示，必须是编译期就明确的常量和宏。[/quote] C99支持variable length array，所以如果用GCC的话是可以的。

user: user-8
content: 可以考虑把数据库中取出的值作为数组的最大有效范围的游标吗?如果直接想简单的修改宏，感觉边角困难

user: user-5
content: 宏,  不是常量也不是变量.  只是编译时的文本替换.  你的问题, 只需要动态申请内存即可.  动态数组, 只有C++高版本的标准才支持.

user: user-9
content: malloc不能用啊？