C语言 strcpy() and char



我想将字符串存储在结构内的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);
}

如果我的实现不正确,请向我建议一种方法来做我打算做的事情。另外,请指出上述代码中的错误。

  1. 在声明function(...)之前,您必须typedef结构errpacket

  2. 函数 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;
}

最新更新