user-0 提问: c语言不定参数出错

回复:
user: user-1
content: 其实电脑开机后物理内存的每个字节中都有值且都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

user: user-2
content: 引用 10 楼 yyang0514 的回复:[quote=引用 5 楼 自信男孩 的回复:][quote=引用 3 楼 yyang0514 的回复:][quote=引用 1 楼 自信男孩 的回复:]#include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h>  int print(const char *format, ...) {     va_list args;     const char *args1;     va_start(args, format);      //printf("%s.....", format);     while(1)     {         args1 = va_arg(args,const char *);         if (args1 == NULL)             break;         printf("%s.....",args1);         /*            if(strlen(args1))            printf("%s.....",args1);            else            break;            */     }     va_end(args);     printf("\n");     return 0; } int main() {     print("aaaaa", "22222", "333333", NULL);     //print("bbbbb", "44444", "5555555", "666666");     return 0; } 供参考～  缺少结束标识 有没有办法在有调用时，不用输入结束符呢。[/quote] 那可以试试用参数个数，即输入一个确定参数用于标识参数的个数[/quote] 非常感谢你的帮助。 请问为什么调用有4个参数，又不要加结束符的时候，输出又是正确的。 print("bbbbb", "44444", "5555555", "666666");[/quote] 这种情况应该是随机的吧，当遇到第5个（越界了）正好是strlen(第5个）长度小于等于0.  越界访问操作是未定义的，结果不确定的。

user: user-0
content: 引用 5 楼 自信男孩 的回复:[quote=引用 3 楼 yyang0514 的回复:][quote=引用 1 楼 自信男孩 的回复:]#include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h>  int print(const char *format, ...) {     va_list args;     const char *args1;     va_start(args, format);      //printf("%s.....", format);     while(1)     {         args1 = va_arg(args,const char *);         if (args1 == NULL)             break;         printf("%s.....",args1);         /*            if(strlen(args1))            printf("%s.....",args1);            else            break;            */     }     va_end(args);     printf("\n");     return 0; } int main() {     print("aaaaa", "22222", "333333", NULL);     //print("bbbbb", "44444", "5555555", "666666");     return 0; } 供参考～  缺少结束标识 有没有办法在有调用时，不用输入结束符呢。[/quote] 那可以试试用参数个数，即输入一个确定参数用于标识参数的个数[/quote] 非常感谢你的帮助。 请问为什么调用有4个参数，又不要加结束符的时候，输出又是正确的。 print("bbbbb", "44444", "5555555", "666666");

user: user-0
content: 引用 7 楼 赵4老师 的回复:无论在编译期还是运行时，我既不事先告诉你总数，也不告诉你用于标记结束参数计数的结束符，实际到底有几个参数，你猜猜看？  请问什么调用有4个参数，又不要加结束符的时候，输出又是正确的。 print("bbbbb", "44444", "5555555", "666666");

user: user-3
content: 要实现智能的可变参数函数，必须依赖编译器支持，否则做不到。即便printf、scanf之类的函数也不是真正智能，实际传入的参数数量和类型完全可以和格式化串中的不一样，它也不知道，还在傻干呢~

user: user-1
content: 无论在编译期还是运行时，我既不事先告诉你总数，也不告诉你用于标记结束参数计数的结束符，实际到底有几个参数，你猜猜看？

user: user-4
content: 供参考： 可变参数在编程中要注意的问题：因 为va_start, va_arg, va_end等定义成宏,所以它显得很愚蠢, 可变参数的类型和个数完全在该函数中由程序代码控制,它并不能智能地识别不同参数的个数和类型. 有人会问:那么printf中不是实现了智能识别参数吗?那是因为函数 printf是从固定参数format字符串来分析出参数的类型,再调用va_arg 的来获取可变参数的.也就是说,你想实现智能识别可变参数的话是要通过在自己的程序里作判断来实现的. 例如，在C的经典教材《the c programming language》的7.3节中就给出了一个printf的可能实现方式. 在实际应用的代码中，程序员必须自己考虑确定参数数目的办法，如： ⑴在固定参数中设标志-- printf函数就是用这个办法。 ⑵在预先设定一个特殊的结束标记，就是说多输入一个可变参数，调用时要将最后一个可变参数的值设置成这个特殊的值，在函数体中根据这个值判断是否达到参数的结尾。 无论采用哪种办法，程序员都应该在文档中告诉调用者自己的约定。 例子，供参考：//下面是一个简单的printf函数的实现，参考了<The C programming language>7.3节中的例子，从固定 //参数format字符串来分析出参数的个数,再调用va_arg 的来获取可变参数.  //如果参数的类型不同呢？因为不同的数据类型占用的字节数可能是不一样的（如double型为8个字符， //short int型为2个），所以很难事先确定应该移动多少个字节！ //但是办法还是有的，这就是使用指针了，无论什么类型的指针，都是占用4个字节，所以，可以把所有 //的传入参数都设置为指针，这样一来，就可以通过移动固定的4个字节来实现遍历可变参数的目的了。  #include <stdio.h> #include <stdlib.h>  void myprintf(char* fmt, ...)//一个简单的类似于printf的实现，参数必须都是int 类型 {     char* pArg=NULL;      //等价于va_list     char c;     pArg = (char *)&fmt;  //对参数取地址     pArg += sizeof(fmt);  //等价于va_start,取得第一个参数地址     do{         c =*fmt;         if (c != '%'){             putchar(c);   //照原样输出字符         }         else{             switch(*++fmt){ //按格式字符输出数据                 case 'd':                         printf("%d",*((int*)pArg));                         break;                 case 'x':                         printf("%#x",*((int*)pArg));                         break;                 default:                         break;             }             pArg += sizeof(int);//等价于va_arg，下一个参数地址         }         ++fmt;     }while(*fmt != '\0');     pArg = NULL;               //等价于va_end     return; } int main(int argc, char* argv[]) {     int i = 13000;     int j = 13500;     myprintf("test1:i=%d\n",i,j);     myprintf("test2:i=%d;%x;j=%d;\n",i,0x57cd,j);      system("pause");     return 0; }  //test1:i=13000 //test2:i=13000;0x57cd;j=13500; //请按任意键继续. . .

user: user-2
content: 引用 3 楼 yyang0514 的回复:[quote=引用 1 楼 自信男孩 的回复:]#include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h>  int print(const char *format, ...) {     va_list args;     const char *args1;     va_start(args, format);      //printf("%s.....", format);     while(1)     {         args1 = va_arg(args,const char *);         if (args1 == NULL)             break;         printf("%s.....",args1);         /*            if(strlen(args1))            printf("%s.....",args1);            else            break;            */     }     va_end(args);     printf("\n");     return 0; } int main() {     print("aaaaa", "22222", "333333", NULL);     //print("bbbbb", "44444", "5555555", "666666");     return 0; } 供参考～  缺少结束标识 有没有办法在有调用时，不用输入结束符呢。[/quote] 那可以试试用参数个数，即输入一个确定参数用于标识参数的个数

user: user-1
content: https://blog.csdn.net/fishe_r/article/details/894559 https://docs.microsoft.com/zh-cn/cpp/cpp/calling-conventions?view=vs-2017

user: user-0
content: 引用 1 楼 自信男孩 的回复:#include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h>  int print(const char *format, ...) {     va_list args;     const char *args1;     va_start(args, format);      //printf("%s.....", format);     while(1)     {         args1 = va_arg(args,const char *);         if (args1 == NULL)             break;         printf("%s.....",args1);         /*            if(strlen(args1))            printf("%s.....",args1);            else            break;            */     }     va_end(args);     printf("\n");     return 0; } int main() {     print("aaaaa", "22222", "333333", NULL);     //print("bbbbb", "44444", "5555555", "666666");     return 0; } 供参考～  缺少结束标识 有没有办法在有调用时，不用输入结束符呢。

user: user-4
content: 主函数：int main() { 	 print("aaaaa", "22222", "333333","");//长度为0的字符串 	 print("bbbbb", "44444", "5555555", "666666",""); 	 return 0; }

user: user-2
content: #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h>  int print(const char *format, ...) {     va_list args;     const char *args1;     va_start(args, format);      //printf("%s.....", format);     while(1)     {         args1 = va_arg(args,const char *);         if (args1 == NULL)             break;         printf("%s.....",args1);         /*            if(strlen(args1))            printf("%s.....",args1);            else            break;            */     }     va_end(args);     printf("\n");     return 0; } int main() {     print("aaaaa", "22222", "333333", NULL);     //print("bbbbb", "44444", "5555555", "666666");     return 0; } 供参考～  缺少结束标识