C语言restrict限定参数别名报错 手动编译正常自动测评失败
报错原因解释
这个error: passing argument 1 to restrict-qualified parameter aliases with argument 3 [-Werror=restrict]报错的核心是你违反了C标准中sprintf函数的restrict限定规则:
C标准库的
sprintf函数声明为int sprintf(char *restrict s, const char *restrict format, ...);,其中restrict关键字要求:所有传入的可变参数对应的内存区域,不能和输出缓冲区s指向的内存区域有重叠。
你代码中写的sprintf(s, "%s%c%d", s, prev, count);,第一个参数是输出缓冲区s,第三个格式化参数也是s,两者指向完全相同的内存区域,属于典型的重叠场景,本身是未定义行为。你手动测试能正常运行只是巧合:未开编译器优化时这种写法可能刚好输出预期结果,但自动测评工具开启了严格编译参数,把这类未定义行为直接判定为错误阻断了编译流程。
修复方案
你要实现往s后追加内容的需求,不能用sprintf直接读写同一块缓冲区,推荐初学者用「临时缓冲区+字符串拼接」的方案改,逻辑清晰不易出错,修改后的完整代码如下:
#include<stdio.h> #include<ctype.h> #include<string.h> #include<stdlib.h> int main(int argc, char* argv[]){ // 补充参数校验,避免无传参时访问argv[1]崩溃 if(argc < 2){ printf("ERROR"); return 0; } char *s = (char *)malloc(sizeof(char) * 100); // 初始化s为空字符串,避免首次拼接出现垃圾值 s[0] = '\0'; // 临时缓冲区存储每次要追加的<字符+计数>片段 char tmp[20]; char prev = argv[1][0]; if(isdigit(prev)!=0){ printf("%s","ERROR"); free(s); return 0; } int count = 1; for(int i=1; i<strlen(argv[1]); i++){ if(isdigit(argv[1][i])!=0){ printf("%s","ERROR"); free(s); return 0; } if(prev==argv[1][i]){ count++; }else{ // 先把当前片段写入临时缓冲区,再追加到s末尾 sprintf(tmp, "%c%d", prev, count); strcat(s, tmp); count = 1; } prev=argv[1][i]; } // 处理循环结束后剩余的最后一组字符 sprintf(tmp, "%c%d", prev, count); strcat(s, tmp); if(strlen(s) > strlen(argv[1])){ printf("%s\n", argv[1]); }else{ printf("%s\n", s); } free(s); return 0; }
上述代码同时修复了原版本缺少参数校验、内存泄漏、缓冲区未初始化的潜在问题,完全符合C标准规范,不会再触发restrict相关报错。
内容的提问来源于stack exchange,提问作者user15409086
相关产品推荐
相关产品推荐

