C:char *问题 [英] C: problem with char*

查看:99
本文介绍了C:char *问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

/*
 * code.c
 *
 * TASK
 *      Reverse a string by reversing pointers. Function should use return
 *      type char* and use a char* parameter as input.
 */
#include <stdio.h>
#include <string.h>
#define STRMAX 51

char* reverse(char* sPhrase[]);

int main() {
    char sPhrase[STRMAX];
    char sReverse[STRMAX];
    printf("Enter string (max. 50 chars): ");
    gets(sPhrase);
    sReverse = reverse(sPhrase);

    return 0;
}

char* reverse(char* sPhrase[]) {
    char* sOutput[STRMAX];
    int iCnt = 0, iCntRev;

    for (iCntRev = strlen(*sPhrase)-2; iCntRev >= 0; iCntRev--) {
        sOutput[iCnt] = sPhrase[iCntRev];
        iCnt++;
    }

    *sOutput[iCnt] = '\0';      // Don't forget to close the string

    return sOutput;
}

此代码有一些怪癖:

  • sReverse = reverse(sPhrase);

  • [错误]分配中的类型不兼容
  • [警告]从不兼容的指针类型传递反向"的arg 1

return sOutput;

  • [警告]函数返回局部变量的地址
  • [警告]从不兼容的指针类型返回

这些警告是什么意思?如何修补错误?该函数应保留char *作为返回类型和参数,因为我正在将这个小程序作为C培训课程的一部分.

What do these warnings mean? How can I patch the errors? The function should keep char* as a return type and as a parameter since I'm making this little program as part of a C training course.

推荐答案

摆脱一些麻烦:

  1. 从不从不使用gets();它会在程序中引入一个故障点.如果传递的缓冲区大小可以容纳10个字符,并且用户键入100个字符,则gets()会很高兴在缓冲区之后立即将多余的90个字符写入内存,从而导致各种混乱.缓冲区溢出是一种简单而常见的恶意软件利用,并且任何使用gets()的代码在设计上都不安全 .改为使用fgets().

  1. NEVER NEVER NEVER use gets(); it will introduce a point of failure in your program. If you pass gets a buffer sized to hold 10 characters, and the user types in 100 characters, gets() will happily write those extra 90 characters to the memory immediately following your buffer, leading to all kinds of mayhem. Buffer overruns are an easy and common malware exploit, and any code that uses gets() is insecure by design. Use fgets() instead.

您不能像在sReverse = reverse(sPhrase);行中那样分配数组对象.如果要复制reverse返回的字符串的内容,则需要使用strcpy()或类似的方法:strcpy(sReverse, reverse(sPhrase));

You cannot assign array objects as you do in the line sReverse = reverse(sPhrase);. If you want to copy the contents of the string being returned by reverse, you need to use strcpy() or similar: strcpy(sReverse, reverse(sPhrase));

分配中的不兼容类型"诊断来自以下事实:您正在尝试将指针值(char *)分配给数组对象(char [STRMAX]).如上所述,您无论如何都无法分配给数组对象.

The "incompatible types in assignment" diagnostic comes from the fact that you are trying to assign a pointer value (char *) to an array object (char [STRMAX]). As I mentioned above, you cannot assign to an array object anyway.

来自不兼容类型的传递参数"警告来自以下事实:您的函数定义未键入以期望指向char的指针,而是期望指向char的指针.将函数定义更改为

The "passing argument from incompatible type" warning comes from the fact that your function definition is not typed to expect a pointer to char, but a pointer to pointer to char. Change the function definition to

char *reverse(char *sPhrase) {...}

为什么用*sPhrase代替sPhrase[](或*sPhrase[])?首先,当数组表达式出现在大多数上下文中时,其类型会从"T的N元素数组"隐式转换为"T的指针"(表达式 decays 转换为指针类型),并且其值设置为数组中第一个元素的地址;该规则的例外情况是:数组表达式是sizeof&(地址)运算符的操作数,或者数组表达式是用于初始化声明中的char数组的字符串文字. .第二,在函数参数定义的上下文中,T a[]T *a相同;两种形式都将a声明为T的指针.

Why *sPhrase instead of sPhrase[] (or *sPhrase[])? First of all, when an array expression appears in most contexts, its type is implicitly converted from "N-element array of T" to "pointer to T" (the expression decays to a pointer type) and its value is set to the address of the first element in the array; the exceptions to this rule are when the array expression is the operand of either the sizeof or & (address-of) operators, or if the array expression is a string literal being used to initialize an array of char in a declaration. Second of all, in the context of a function parameter definition, T a[] is identical to T *a; both forms declare a as a pointer to T.

当您在main中调用reverse(sPPhrase);时,表达式sPPhrase的类型将从"STRMAX元素数组char"衰减为"pointer to char",因此需要在函数中键入形式参数如char *.

When you call reverse(sPPhrase); in main, the type of the expression sPPhrase decays from "STRMAX-element array of char" to "pointer to char", so the formal parameter in the function needs to be typed as char *.

由于下标是根据指针算术定义的,因此您仍然可以将下标运算符应用于sPhrase,但是请记住sPhrase是 pointer 值,而不是数组.

You can still apply the subscript operator to sPhrase, since subscripting is defined in terms of pointer arithmetic, but remember that sPhrase is a pointer value, not an array.

正如您目前所写的那样,reverse需要一个类型为char *[]的参数,该参数与char **相同,就好像您要传递一个指向char的指针数组而不是char数组一样.同样,您需要将reverse中的sOutput变量声明为char sOutput[STRMAX];,而不是char *sOutput[STRMAX];(后者将sOutput声明为指向char的指针数组,这不是您想要的;这是以及从不兼容的类型返回"警告).

As you currently have it written, reverse expects a parameter of type char *[], which is identical to char **, as though you were passing an array of pointer to char, rather than an array of char. Similarly, your sOutput variable in reverse needs to be declared char sOutput[STRMAX];, not char *sOutput[STRMAX]; (the latter declares sOutput as an array of pointer to char, which is not what you want here; this is the source of the "return from incompatible types" warning as well).

返回本地变量的地址"警告来自以下事实:您正在尝试返回该函数本地的,具有自动范围的变量的地址.一旦函数退出,该变量将不再存在,并且存储在该位置的值可能不再有效.有几种解决方法:

The "return address of local variable" warning comes from the fact that you are trying to return the address of a variable that's local to the function and has automatic extent. Once the function exits, that variable no longer exists, and the value stored at that location may no longer be valid. There are several ways around this:

  1. 将sOutput声明为静态:static char sOutput[STRMAX];.这将导致sOutput的内存在程序启动时分配,并保持分配状态,直到程序退出,因此数组的内容将在对reverse的调用之间保持不变.该变量仍然是函数的局部变量(不能通过该函数外部的名称进行访问).但是,这意味着该函数不再是线程安全的,并且是一个丑陋的解决方案.

  1. Declare sOutput as static: static char sOutput[STRMAX];. This will cause the memory for sOutput to be allocated at program startup and stay allocated until the program exits, so the contents of the array will persist between calls to reverse. The variable is still local to the function (it cannot be accessed by name outside of that function). However, this means the function is no longer thread-safe, and it's an ugly solution.

动态地在reverse中分配一个缓冲区并返回其地址.这样做的好处是您可以根据需要调整缓冲区的大小,而不必担心线程安全性.缓冲区将一直保留,直到您明确地取消分配它为止(或直到​​程序退出).缺点是,调用者现在需要在完成内存后负责分配该内存.避免内存管理麻烦的最好方法是首先避免内存管理,而这个问题并不是真正需要的.

Dynamically allocate a buffer within reverse and return the address of that. The virtue of this is that you can size the buffer as needed, and you don't have to worry about thread safety. The buffer will persist until you explicitly deallocate it (or until the program exits). The disadvantage is that the caller is now responsible for deallocating that memory when it's finished with it. The best way to avoid headaches with memory management is to avoid memory management in the first place, and this problem doesn't really call for it.

在适当的位置执行反向操作(即,在输入数组中执行反向操作),然后返回输入数组的地址.这意味着您正在破坏您的输入,这可能不是您想要的.

Perform the reverse in place (that is, do the reverse within the input array), and return the address of the input array. This means you're clobbering your input, which may not be what you want.

将目标数组作为第二个输入传递给函数,而不必担心返回值(或者,如果您必须返回某个值,则返回目标数组的地址):

Pass the destination array as a second input to the function and don't bother with a return value (or, if you have to return something, return the address of the destination array):


    char *reverse(char *src, char *dst)
    {
      // write contents of src in reverse order to dst
      return dst;
    }
    ...
    reverse(sPPhrase, sPReverse);

这是像strcpy()这样的函数的工作方式,因此有这样做的先例,并且在所有选项中痛苦最小.

This is how functions like strcpy() work, so there's precedent for doing this, and it's the least painful of all the options.

请记住,C语言中的字符串处理非常 (在这里我们所说的是石刀和熊皮),还有许多其他语言有意义的概念(例如使用=分配字符串内容)实际上并不适用于C.

Just remember that string handling in C is very primitive (we're talking stone knives and bearskins here), and a lot of concepts that make sense in other languages (like using = to assign string contents) don't really apply in C.

这篇关于C:char *问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆