首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C中的指针问题--我在这里做错了什么?

C中的指针问题--我在这里做错了什么?
EN

Stack Overflow用户
提问于 2010-03-06 01:55:23
回答 2查看 255关注 0票数 2

作为一点背景知识,我正在用C语言为一台运行DOS专有版本的小型16位手持计算机编写一个抄表应用程序。

我有一个屏幕,它显示仪表信息并提示用户键入读数。当用户按下设备上的enter键时,将执行以下代码:

代码语言:javascript
复制
/* ...
 * beginning of switch block to check for keystrokes
 * ...
 */
case KEY_ENTER: {
    /* show what has been entered */
    if(needNew == 0) {
        /* calculate usage for new reading */
        double usg = 0;
        int ret = CalculateNewUsage(vlr, buf, &usg);
        VerifyReadScreen(vlr, ret, buf, &usg);
        needRedraw = TRUE;
    }
    break;
}
/* .... end switch statement */

vlr是一个指向保存所有帐户/计价器信息的结构的指针,buf的类型为char[21],用于存储在此块之上处理的读数的数字击键。当我在调用CalculateNewUsage之前和之后检查它们时,我的变量都包含有效数据。

然而,当我在输入VerifyReadScreen后再次检查变量数据时,newread指向内存中的某个随机位置,并返回看起来像版权声明的内容。有趣的是,无论我输入什么帐户或读数,屏幕上都会打印出VerifyReadScreennewread的无效数据。我以与CalculateNewUsage相同的方式将地址传递给VerifyReadScreen,但不知何故我得到了不同的结果。

这是VerifyReadScreen

代码语言:javascript
复制
BYTE VerifyReadScreen(const VLRREC * vlr,
                        const int status,
                        const char * newread,
                        const double * usage) {

    /* snip a whole bunch of irrelevant formatting code */

    printf("%s", (*newread)); /* prints funky copyright text */

    /* snip more irrelevant formatting code */
    return TRUE;
}   

感谢Jefromi指出,我在VerifyReadScreen中实际打印newread的代码应该是:

代码语言:javascript
复制
printf("%s", newread); /* yay! */

因为我不需要取消引用newread,因为printf为我做了这件事。我本质上是在传递一个指向一个指针的指针,这个指针是内存中的某个任意位置。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-03-06 02:16:17

我想我有足够的信心把这篇文章作为答案:

代码语言:javascript
复制
BYTE VerifyReadScreen(const VLRREC * vlr, const int status, const char * newread, const double * usage) {
...
    LCD_set_cursor_pos(19 - strlen(newread), 3);
    printf("%s", (*newread)); /* prints funky copyright text */
...
}

您已经获得了一个字符串(char*) newread,但是在这个printf中,您取消了对它的引用,这就得到了字符串的第一个字符。然后将其用作printf的%s的参数,因此它尝试转到该字符给出的内存地址,并打印它在那里找到的内容。

附注:你很不走运--一般来说,这样做可能会给你一个段错误,所以你可以追踪到那一行,并意识到那里有一个指针错误。

票数 7
EN

Stack Overflow用户

发布于 2010-03-06 02:20:27

我不知道这是否是您面临的问题,但是VerifyReadScreen中使用的21个字符的buffer很可能会溢出:

代码语言:javascript
复制
if(strlen((*vlr).ServAdd) >= 20) {
    sprintf(buffer, "%20s", (*vlr).ServAdd);
}

%20s格式说明符不会阻止sprintf写入超过20个字符。如果字符串少于20个字符(或者在if条件中需要<= 20?),它只用空格填充字符串。

代码语言:javascript
复制
else {
    memset(buffer, 0x20, (int)(strlen((*vlr).ServAdd) / 2) + 1);
    strcat(buffer, (*vlr).ServAdd);
}

在这里,根据字符串的长度进行了一些填充,但是我不知道如何确保结果不超过20个字符。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2388822

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档