我是学习 C 的新手,我正在练习内存分配和指针,但是我遇到了一个无法解决的问题。当我调试下面的代码时,我收到一条错误,指出“Cannot Access Memory at Address” for line VowelStore[x] = VowelA;
char *DissVowel(char phrase[50])
{
char vowelStore[50];
for(int x=0; x< strlen(phrase); x++)
{
switch(phrase[x])
{
char *vowelA = malloc(sizeof(*vowelA));
case 'a':
vowelA = phrase[x];
vowelStore[x] = vowelA;
free(vowelA);
break;
default:
break;
}
}
return vowelStore;
}
基本上,这个函数接收一个字符数组(一个字符串短语),然后循环遍历每个字符,如果当前字符是“a”,则分配一 block 内存,并将“a”存储在分配的空间。接下来,包含“a”的这个空间的地址将被存储在一个单独的数组中,该数组将包含多个地址。然后该函数返回该地址数组。
非常感谢任何帮助!
最佳答案
您的代码存在许多问题。
char *DissVowel(char phrase[50])
这是合法的,但具有误导性。 C 实际上没有数组参数。如果您定义了看起来像数组参数的内容,就像您在此处所做的那样,它会被“调整”为指针参数 - 并且长度会被悄悄忽略。上面完全等同于:
char *DissVowel(char *phrase)
for(int x=0; x< strlen(phrase); x++)
这是合法但效率低下的。 strlen()
必须从头开始扫描字符串,以找到标记字符串结尾的终止 '\0'
空字符。您在每次迭代时调用 strlen
。将字符串长度保存在变量中并在条件中测试该长度,或者使用不同的条件,例如 phrase[x] != '\0'
。 (非常小的一点:i
是用作索引的迭代变量的更常规名称。)
switch(phrase[x])
{
char *vowelA = malloc(sizeof(*vowelA));
case 'a':
/* ... */
break;
default:
break;
}
switch
语句本质上是一个计算的goto
。执行 switch
时,它会直接跳转到 case 'a':
标签或 default:
标签,跳过中的任何内容之间。由于进入了新的作用域,因此为指针对象vowelA本身分配了内存,但其初始化并未执行,因此vowelA具有不确定的值。
return vowelStore;
vowelStore
是一个局部数组变量。在这种情况下,它被“转换”为指向数组初始元素的指针,相当于 &vowelStore[0]
。当您从函数返回时,数组变量将不再存在,因此您返回的值是一个悬空指针。
您应该了解如何在编译器中启用更多警告;它应该能够警告您至少其中一些问题。
关于C 无法访问地址处的内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39431117/