出于某种原因,这不起作用:
const char * str_reset_command = "\r\nReset";
const char * str_config_command = "\r\nConfig";
const char *commands[2] = {
&str_reset_command,
&str_config_command
};
这是对的吗? (其他地方的代码是否必然导致问题?)
(我在基线8位微控制器上运行它并且具有非常有限的调试功能)
澄清:
这就是我想要实现的目标:
const char * str_reset_command = "\r\nReset";
const char * str_config_command = "\r\nConfig";
const char * str_start_command = "\r\nStart";
const char * str_end_command = "\r\nEnd";
const char * const group0[1] = {
str_reset_command
}
const char * const group1[2] = {
str_reset_command,
str_start_command
}
const char * const group2[3] = {
str_reset_command,
str_start_command,
str_end_command
}
void doStuffToCharacter(unsigned char the_char){
// ....
}
void doStuffToGroup(char ** group, unsigned char num_strings){
for (unsigned char s=0; s < num_strings; s++){
unsigned char idx = 0;
while (group[s][idx]){
doStuffToCharacter(group[s][idx]);
}
}
}
void main (void){
doStuff(group0, 1);
doStuff(group1, 2);
doStuff(group2, 3);
}
除了更正之外,我们还欢迎任何更简洁的建议。
需要将命令字符串的各种组合发送到函数进行处理。所有字符串都将在ROM中,指向它们的指针组也是如此。
答案 0 :(得分:4)
您创建了一个指针数组,但是您传递的是指针的地址(意思是指向指针的指针)。你应该做的是这个 -
const char* commands[2]= {str_reset_command, str_config_command};
答案 1 :(得分:3)
不直接回答你的问题,但为什么不试试这个:
typedef enum {
RESET_CMD,
CONFIG_CND
} cmd_id;
const char *commands[2] = {
"\r\nReset",
"\r\nConfig"
};
而不是像这样使用它:
commands[RESET_CMD]
修改强>
我会重写您的澄清以匹配此方法:
typedef enum {
RESET_CMD,
CONFIG_CND,
START_CMD,
END_CMD
} cmd_id;
const char *commands[4] = {
"\r\nReset",
"\r\nConfig",
"\r\nStart",
"\r\nEnd"
};
const cmd_id group0[1] = {
RESET_CMD
};
const cmd_id group1[2] = {
RESET_CMD,
START_CMD
};
const cmd_id group2[3] = {
RESET_CMD,
START_CMD,
END_CMD
};
void doStuffToCharacter(unsigned char the_char){
// ....
}
void doStuffToGroup(const cmd_id group[], unsigned char num_cmds){
for (unsigned char s=0; s < num_cmds; s++) {
unsigned char idx = 0;
while (commands[group[s]][idx]) {
doStuffToCharacter(commands[group[s]][idx++]);
}
}
}
void main (void){
doStuff(group0, 1);
doStuff(group1, 2);
doStuff(group2, 3);
}
答案 2 :(得分:2)
你有一个const char指针数组,你试图在其中存储指向const char指针的指针。删除&
运算符,它应该可以正常工作。
答案 3 :(得分:1)
如果在函数外部声明了变量,则初始值设定项必须是常量。在这种情况下,Const不计算在内。您将创建一个指向指针的数组,然后使用char *变量的地址。
const char * str_reset_command = "\r\nReset";
const char * str_config_command = "\r\nConfig";
const char **commands[2] = {
&str_reset_command,
&str_config_command
};
使用数组时不要忘记取消引用指针。
const char* string = *commands[1] ; //actually it is *(commands[1]) but the [] operator has higher precedence anyway
答案 4 :(得分:1)
试试这个。这不是你想要的,但它完成了这项工作。
#define RESET_COMMAND "Reset"
#define CONFIG_COMMAND "Config"
const char *commands[2] = {
RESET_COMMAND,
CONFIG_COMMAND,
};
int
main() {
...
}
答案 5 :(得分:1)
您正在使用全局变量。你真的确定你需要这种方法吗?
按照原样遵循您的代码,您将str_reset_command
定义为const char *
。这意味着它是一个指向char的指针,它也具有限定符const
。你不必将“const”与const
混淆。 :)
编译器将每个表达式构建的“const”视为涉及文字的表达式
另一方面,const
限定符意味着您正在定义一个“变量”,其值不能被修改,除非在其定义的那一刻。
表达式"\r\nReset"
是一个“const”,因为它是一个字符串文字
但是const char * str_reset_command
不是“const”,而是一个无法修改的变量。
不同之处在于文字是编译器的“常量”,因为它可以在编译时计算它们的值。但是,const
对象作为变量保存,因为其值可以在执行时间中确定。例如,考虑const
中几个函数的<string.h>
参数。
您的变量group0
被定义为指向char数组的指针
由于它被定义为全局变量,因此其初始化程序必须是“const”(在编译时间意义上)值。但是你提供了str_reset_command
,它不是文字(或只涉及文字的表达)。因此,其值不能在编译时确定,也不能用作初始化。
也许您可以尝试编写初始化函数:
const char * str_reset_command = "\r\nReset";
const char * str_config_command = "\r\nConfig";
const char * str_start_command = "\r\nStart";
const char * str_end_command = "\r\nEnd";
char * group0[1];
char * group1[2];
char * group2[3];
void initGroups(void) {
group2[0] = group1[0] = group0[0] = str_reset_command;
group2[1] = group1[1] = str_start_command;
group2[2] = str_end_command;
}
int main(void) {
initGroups();
// Do stuff...
}
我删除了const
限定符,因为现在我们需要修改指针。
无论如何,使用全局变量会产生一些副作用 如果可能,尝试修改此方面。
修改强>
第二次尝试
我在你的计划中思考,我完全改变了你的方法 首先,我不明白你为什么要使用所有那些“group []”数组 由于您希望优化内存资源,因此这不是最佳选择 另一方面,你的“常量字符串”似乎只有少数 通过假设它们不超过8,给定组中涉及的字符串的信息可以保持为1个字节 我的意思是,您可以通过一个字节的位来定义“组”或“集合”,因此如果给定的成员属于该集合,则将位1(打开),以及0。
此外,由于您接受使用指向常量字符的指针数组,我认为所有字符串都可以在代码开始时保存在常量字符数组中。这可以通过const声明保存在ROM中。
您使用的名称为str_reset,str_start等 您似乎需要自己清楚地了解这些信息 这些信息可以通过编译器常量和/或枚举保存在代码中,编译器常量和/或枚举在编译程序中没有任何成本。
我设计了一个使用位屏蔽的代码
这样您最多可以使用8个字符串
由于位掩码是2的幂,因此不能用作数组索引
但是,可以用一种非常结果的方式定义一个名称与位掩码常数“并行”的枚举常量列表。
特别是,您将能够或更改枚举的顺序,但您的代码将继续工作。
为了完成图片,我使用了C99 / C11标准的功能(您似乎使用了,因为您声明for
语句的方式),这允许我们初始化数组的独立成员通过写出所需的索引
由于索引现在将具有枚举给出的名称,因此您可以信任此技术,而无需关注已使用的实际索引。
我使用<stdio.h>
和printf()
来测试该程序。你可以删除这些行。
#include <stdio.h>
#define bit0 0x01u /* Binary 0000 0001 */
#define bit1 0x02u /* Binary 0000 0010 */
#define bit2 0x04u /* Binary 0000 0100 */
#define bit3 0x08u /* Binary 0000 1000 */
#define bit4 0x10u /* Binary 0001 0000 */
#define bit5 0x20u /* Binary 0010 0000 */
#define bit6 0x40u /* Binary 0100 0000 */
#define bit7 0x80u /* Binary 1000 0000 */
enum {reset_command = 0, config_command, start_command, end_command};
#define bit_reset (1u << reset_command) /* Equal to bit0 */
#define bit_config (1u << config_command) /* Equal to bit1 */
#define bit_start (1u << start_command) /* Equal to bit2 */
#define bit_end (1u << end_command) /* Equal to bit3 */
const char * const str[] = {
[reset_command] = "\r\nReset",
[config_command] = "\r\nConfig",
[start_command] = "\r\nStart",
[end_command] = "\r\nEnd"
};
const unsigned char bitgroup0 = bit_reset;
const unsigned char bitgroup1 = bit_reset | bit_start;
const unsigned char bitgroup2 = bit_reset | bit_start | bit_end;
void doStuffToCharacter(unsigned char the_char){
printf("%c", the_char);
}
void doStuff(const char * const * str, unsigned char bitgroup){
printf("\n\nGroup: %hu\n", bitgroup);
for (unsigned char b=bitgroup, j=0; b; b >>= 1u, j++){
if (b & 1u) {
for(unsigned char idx = 0; str[j][idx]; idx++) {
doStuffToCharacter(str[j][idx]);
}
}
}
}
int main (void){
doStuff(str, bitgroup0);
doStuff(str, bitgroup1);
doStuff(str, bitgroup2);
}
如您所见,每个“组”现在只需要1个字节。 (您的方法至少使用了1,2和3个字节)
for()
语句中的迭代次数不超过groupbit
参数中的最大位“on”。
const char
指针中保存const
对象的要求也已满足。
数组的大小由编译器自动确定,以保存最大索引。
for()
循环遍历一个“byte”,初始化为您作为参数传递的“group”。
最后一位针对1进行测试
如果该位为1,则执行一些操作
否则,这将被跳过进入下一次迭代
通过赋值b >>= 1u
删除最后一位。
每次迭代,我们都需要离开数组j
的索引str
。
因此,当且仅当j
- 字符串被处理时,j
- 位为1
接下来,重复每一次,直到b
没有更多位1
。
如果使用位1都是连续的“组”,则程序的工作方式与您在示例中的预期方式相同。
现在您可以选择所需的操作,只需切换相应的位即可。
答案 6 :(得分:1)
您的数组声明与使用它的函数的原型不一致:
const char *commands[2] = { // <- declared as array of 2 pointers to char
doStuffToGroup(char ** group // <- used as pointer to pointer to char
这是一个常见的C / C ++缺陷(尽管用作香草数组的重新设计的矢量在C ++中的使用率却远不如此)。
有关更详细的说明,请参阅this answer。