ESP32项目队列代码编译报错:array subscript has type 'char' [-Werror=char-subscripts] 求助
嘿,我来帮你理清楚这个问题~ 首先这个编译报错本质是编译器在提醒你用char类型做数组下标不安全,因为绝大多数编译器里char默认是有符号类型,万一front/rear变成负数(比如你初始化front是-1),访问数组的时候就会直接越界搞出未定义行为,再加上你可能开了-Werror把警告当成错误处理,所以就直接报错了。
下面分步骤帮你解决所有问题:
1. 先搞定编译报错:替换成安全的下标类型
把队列结构体里的front和rear从char改成int(或者用size_t,这是C标准里专门用来表示大小/下标的无符号类型,更规范):
// FIFO queue structure for tracking the keys typedef struct { char items[6]; int front; // 把char改成int int rear; // 把char改成int } Queue;
这样编译器就不会再报下标类型的错误了,int作为数组下标完全合法,也能避免有符号char的负数风险。
2. 修正队列的数组越界bug
你现在的代码有个隐藏的内存越界问题!你的数组是char items[6],合法下标是0~5,但你的isFull判断是q->rear ==6,这时候执行q->items[q->rear] = value会访问items[6],这已经超出数组范围了,轻则程序行为异常,重则直接崩溃。
按照你“满了就自动挤掉队首元素”的需求,调整Enqueue逻辑:
// Check if the queue is full bool isFull(Queue* q) { return (q->rear == 6); } // Enqueue an element void Enqueue(Queue* q, char value) { if (isFull(q)) { // 队列满了,把所有元素往前挪一位,挤掉最老的队首元素 for (int i = 0; i < 5; i++) { q->items[i] = q->items[i + 1]; } q->rear = 5; // 挪完之后,最后一个空位下标是5 } q->items[q->rear] = value; q->rear++; }
这样每次满了之后,数组里的元素整体前移,新元素放到最后,不会出现越界的情况。
3. 修复字符串比较的坑
你现在用strcmp(buffer.items, wildString)有个隐患:strcmp要求字符串必须以'\0'结尾,但你的items[6]数组刚好存6个字符,没有多余的位置放终止符,strcmp会一直读取数组后面的内存直到找到'\0',比较结果完全不可控。
换成memcmp来比较前6个字符更靠谱,它不需要终止符,直接按字节比较指定长度:
// beep if the buffer matches desired string if (memcmp(buffer.items, wildString, 6) == 0) { xTaskCreate(beep, "beep", configMINIMAL_STACK_SIZE, (void *)3, 5, NULL); }
记得要确保代码里包含了string.h头文件,memcmp就在这个文件里。
备注:内容来源于stack exchange,提问作者StarSword

