这个问题在这里已有答案:
我有一个看起来像这样的功能:
void functionname(int a, char* c){
sprintf(c, " ... some text ...");
}
上面的语句使用sprintf写入'c'数组 .
对于我的系统,我不认为我可以使用sprint,因为我使用的是不同的(嵌入式)操作系统 .
打印功能我使用的东西看起来像snprintf,我想知道如何使这个功能与snprintf一起使用 .
我是否使用strlen(c)?当c为空时会发生什么?,我使用sizeof(c)吗?
snprintf(c, sizeof(c), " ... text");
要么
snprintf(c, strlen(c), "... text");
调用'functionname'的函数有一个数组,它将c的长度定义为c [64] . 我担心调用sizeof(c)会导致指针的大小 . 还担心当数组不包含字符串时strlen将导致返回0 .
所以问题是如何告诉snprintf达到c [64]的这个值 .
如何获得指针c指向的数组的大小,并将此答案放在snprintf函数中 . 如果有一种方法可以从sprintf()到snprintf()使用相同的变量,那么可以提供给sprintf()?在sprint()函数以char指针为目标的情况下?
5 回答
除了几个例外,
sizeof
是编译时可评估的,并为您提供类型的大小 . 因此,它无法知道运行时间的事情,比如"string"的长度 .strlen
在const char*
上运行,并沿着内存从起始指针跟踪,直到达到第一个\0
,然后返回它所产生的进度数 . 's convenient since it can be used to compute the length of a 1072277 , assuming it'被建模为一系列以零字节终止的非零字节 .在这段代码中:
c
仅仅是一个指针,而不是一个数组 . 所以sizeof(c)
将是sizeof(char *)
,即2,4或8,具体取决于体系结构(分别为16,32或64位) .strlen(c)
仅在c
开始的内存中给出第一个空位置 . 如果调用者将数组初始化为0,那么它将只是...0
!所以这里都不能使用 . 最好的方法是让调用者传递数组的实际大小,并对被调用者有信心:
你不能 .
代码需要跟踪指针指向的有效内存量 .
指针不保存它指向的有效存储器大小的信息,而只保存存储区的地址,甚至可能是0的大小 .
http://linux.die.net/man/3/snprintf声明snprintf中的size参数包含将要写入的最大字符数;这是一种防止写入超出c的任何存储开始的保护 . (顺便说一句,
c
?为什么不s
?) .snprintf
无法找到最大值 . 目的地的可用内存大小应该从分配时(动态或通过数组定义)得知 .编辑:在一般情况下,必须将
c
处可用的字节数作为参数传递给functionname
(出于同样的原因,必须将其传递给snprintf
) . 如果函数可以共享(例如通过标头)数组大小的#define,或者可以访问包含内存大小的全局变量,那么这可能不是必需的.--这就是说:如果你确定c的内存足够,或者如果你进入不安全的程序,你当然可以将一些大数字传递给
snprintf
. 只要内存确实足以用于在运行时写入的文本,这将起作用 .snprintf
的size
参数只是将上限传递给snprintf
,这将在运行时触及超出其需要触摸的内存 .由于
c
是指针,sizeof(c)
将返回指针的大小,这取决于平台的体系结构,例如32位 - > 4,16位 - > 2 .strlen(c)
也不会帮助你,因为它通过停在第一个空字符来计算字符串的长度 .如果您的缓冲区未初始化,则不会比未定义的行为更好 .
您需要知道
c
引用的缓冲区的实际大小 .缓冲区可以静态分配在堆栈上,如下所示:
或动态:
您需要知道它的实际大小(此处为250),将其明确地传递给调用sprintf变体的函数:
我在这里假设
a
是一个完全不相关的变量 .