C字符串文字处理

C字符串文字处理,c,string,segmentation-fault,C,String,Segmentation Fault,以下程序崩溃的代码段有什么问题-给出分段错误。我正在使用gcc uint8_t result = 1 InsertRow("Name","Details of work",result); void InsertRow(char *Name, char *Description,uint8_t Result) { char Buffer[500]; if(Result==1) sprintf(Buffer,"<tr&g

以下程序崩溃的代码段有什么问题-给出分段错误。我正在使用gcc

uint8_t result = 1      

InsertRow("Name","Details of work",result);     

void InsertRow(char *Name, char *Description,uint8_t Result)   
{  
   char Buffer[500];  

   if(Result==1)   
      sprintf(Buffer,"<tr><td>%s </td> <td> %s </td> <td>  %s </td></tr>",Name,Description,Result);   
} 
uint8\u t结果=1
插入行(“名称”、“工作细节”、结果);
void InsertRow(字符*名称、字符*描述、uint8\u t结果)
{  
字符缓冲区[500];
如果(结果==1)
sprintf(缓冲区,“%s%s%s”,名称、说明、结果);
} 

您正在为类型为
uint8\u t
的参数使用
%s
格式说明符,它应该是
%u
,您应该将值强制转换为
unsigned int
。这使您不必关心确切的类型和调整格式化程序(如评论员所建议的)

当然,我们也很难知道缓冲区是否足够大。如果有,可以使用
snprinf()
来避免这种情况。

这里

sprintf(Buffer,"<tr><td>%s </td> <td> %s </td> <td>  %s </td></tr>",Name,Description,Result);    
sprintf(缓冲区,“%s%s%s”,名称、描述、结果);
您正在将
结果
(类型为
uint8\u t
)作为指向字符数组的指针传递

这意味着整数值将被表示为一个指针,它很可能指向您无法访问的内存——因此seg。过错您需要将第三个
%s
替换为适当的格式标志,以将值打印为整数


注意:在这种情况下,不要直接使用
%d
,因为您的
uint8\u t
类型不能保证与
int
大小相同(很可能不是)。如果您首先将
结果的值转换为
int
(int)Result

结果不是字符*,则可以使用
%d
,考虑使用
snprintf
防止缓冲区溢出。对于
uint8
,格式应为
PRIu8
%hhu
也可能是正确的
%u
代表
unsigned int
@Daniel:
uint8\u t
是否保证作为vararg被提升为
unsigned int
?因此,
%u
将打印它。我同意最好使用format宏,而不是试图解决这个问题。@SteveJessop在我理解整数提升时,“如果一个int可以表示原始类型的所有值(受宽度限制,对于一个位字段),该值将转换为int;”,则提升为
int
。所以从技术上讲,它应该是UB,但我不认为有任何实现不能按预期工作。@Daniel:很公平。在
va_arg
中有一个特殊情况,即“一种类型是有符号整数类型,另一种类型是相应的无符号整数类型,并且值在两种类型中都可以表示”时就可以了。所以我确实认为,
%u
是可以的,但事实上,我已经犯了一个错误试图证明它是正确的,这表明我不应该提倡它:-)IIRC
printf
-风格的函数奇怪地对参数提出了比varargs更严格的限制,所以你可能是对的,这是UB,尽管很难想象一个实现除了工作之外还能做什么。@SteveJessop啊,这可能会让它定义行为。但我不确定,法律语言不是我的第一语言。无论行为是明确的还是未明确的,它几乎肯定会起作用。