我想将字符串存储在结构内的char数组中,当我访问char数组时,我希望结果与全局变量errCode中的值一起显示。当我访问结构的 errDesc 成员时,我希望结果是"检测到错误,错误代码为 0xA0B0C0D0",但由于使用 strcpy 复制字符串,我得到的结果是"检测到错误,错误代码为 %08lx"。这是一个复制我的问题的示例代码:
int errCode = 0xA0B0C0D0;
void function(errpacket* ptr, int a, char* errString, ...);
typedef struct{
int err;
char errDesc;
}errpacket;
int main(){
errpacket* a;
void function(a, 10, "Error detected with error code %08lx", errCode);
return 0;
}
void function(errpacket* ptr, int a, char* errString, ...){
ptr->err = a;
strcpy(&ptr->errDesc, errString);
}
如果我的实现不正确,请向我建议一种方法来做我打算做的事情。另外,请指出上述代码中的错误。
-
在声明
function(...)
之前,您必须typedef
结构errpacket
-
函数
main()
中的变量a
只是一个指针。如果您尝试写入未初始化的指针,则会在函数内出现分段错误。
成员errDesc
将只保存一个字符,而不是字符串或字符数组。
试试这个...
int errCode = 0xA0B0C0D0;
typedef struct {
int err;
char* errDesc;
} errpacket;
void function (errpacket* ptr, int a, char* errString, ...);
int main () {
errpacket a;
function(&a, 10, "Error detected with error code %08lx", errCode);
return 0;
}
void function (errpacket* ptr, int a, char* errString, ...) {
ptr->err = a;
ptr->errDesc = strdup( errString);
}
请尝试以下修复:
#include <stdarg.h> //to be added for vsprintf use
int errCode = 0xA0B0C0D0;
void function(errpacket* ptr, int a, char* errString, ...);
typedef struct{
int err;
char *errDesc;
}errpacket;
int main(){
errpacket a; //you need allocate memory if you use a pointer here
void function(&a, 10, "Error detected with error code %08lx", errCode);
return 0;
}
void function(errpacket* ptr, int a, char* errString, ...){
ptr->err = a;
ptr->errDesc = malloc(strlen(errString)+1);
memset(ptr->errDesc, 0, strlen(errString)+1);
/*if(ptr->errDesc != NULL)
{
strcpy(ptr->errDesc, errString);
}*/
// use like following if you want use a formatted string
if(ptr->errDesc != NULL)
{
va_list args;
va_start (args, errString);
vsprintf (ptr->errDesc, errString, args);
va_end (args);
}
}
不能使用单个char
变量来保存整个字符串。
您可以做的是将errDesc
声明为固定长度的数组(如果您知道错误描述可以包含的最大字符数(,或者使用 malloc
动态分配并稍后使用 free
释放的指针。
阵列案例:
#define MAX_ERR_STRING_SIZE 500
typedef struct
{
int err;
char errDesc[MAX_ERR_STRING_SIZE];
} errpacket;
// You can now use strcpy() to copy to errpacket::errDesc assuming none of the error strings exceed MAX_ERR_STRING_SIZE
动态内存:
typedef struct
{
int err;
char *errDesc;
} errpacket;
// Take note of the new parameter: int errStringLength,
void function(errpacket* ptr, int a, char* errString, int errStringLength, ...){
ptr->err = a;
ptr->errDesc = malloc((errStringLength + 1) * sizeof(char));
if(ptr->errDesc == NULL)
{
perror("malloc");
exit(EXIT_FAILURE);
}
strcpy(&ptr->errDesc, errString);
}
使用完ptr
后,需要调用free(ptr->errDesc);
来取消分配字符串。
我认为你真的不想要一个带有变量参数的函数,比如printf。下面的解决方案只期望您最终使用的参数。请注意,我不使用用户提供的格式字符串;这被视为安全风险。我还使用了snprintf
(而不是简单的sprintf
(以防止错误消息长于结构中的数组大小。数组大小是一个定义,因此可以轻松更改。
具体修复:
- 正确的声明顺序(在使用之前定义结构类型(
- 定义一个实际的错误数据包对象(而不仅仅是指向一个对象的未初始化指针(
- 在错误数据包中为消息提供实际内存
- 为错误数据包提供打印功能
- 不要让用户代码指定 printf 格式;打印用户提供的字符串,并带有长度保护的
%s
格式说明符。 - 不要使用变量参数函数(无论如何都不会计算其多余的参数(;只需显式声明所需的参数即可。
.
#include<stdio.h>
int errCode = 0xA0B0C0D0;
#define MAX_ERRDESC_LEN 80 // avoid literals
typedef struct{
int err;
char errDesc[MAX_ERRDESC_LEN]; // provide actual space for the message
}errpacket;
void printErrPack(FILE *f, errpacket *ep){
fprintf(f, "Error packet:n");
fprintf(f, " err = 0x%x:n", ep->err);
fprintf(f, " desc = ->%s<-n", ep->errDesc);
}
// Standard function with fixed argument count and types
void function(errpacket* ptr, int errNo, char* errString, int errCodeArg){
ptr->err = errNo;
// snprintf "prints" into a string
snprintf( ptr->errDesc, // print destination
MAX_ERRDESC_LEN, // max length, no buffer overflow
"%s with error code %x", // do not use user string as format
errString, // user supplied string, printed via %s
errCodeArg );
}
int main(){
errpacket a; // define an actual object, not a pointer
// pass the address of the object a
function(&a, 0xdead, "Error detected ", errCode);
printErrPack(stdout, &a);
return 0;
}