itsource

C 함수에서 문자열을 반환하는 중

mycopycode 2022. 8. 29. 22:23
반응형

C 함수에서 문자열을 반환하는 중

C는 3년 이상 사용하지 않아서 많은 것에 익숙치 않습니다.

바보같이 보일 수도 있지만 함수에서 문자열을 반환할 수 없습니다.음음음음음음음음음음음음음음음 음할 수 string.h이걸 위해서.

코드는 다음과 같습니다.

#include <ncurses.h>

char * getStr(int length)
{   
    char word[length];

    for (int i = 0; i < length; i++)
    {
        word[i] = getch();
    }

    word[i] = '\0';
    return word;
}

int main()
{
    char wordd[10];
    initscr();
    *wordd = getStr(10);
    printw("The string is:\n");
    printw("%s\n",*wordd);
    getch();
    endwin();
    return 0;
}

수 .getStr기능)이 올바르게 표시되지 않습니다(가비지가 표시됩니다).

도움에 감사드립니다.

발신측 스택에 스트링을 할당하고, 그 스트링을 기능에 전달합니다.

void getStr(char *wordd, int length) {
    ...
}

int main(void) {
    char wordd[10 + 1];
    getStr(wordd, sizeof(wordd) - 1);
    ...
}

으로 만들 도 있어요.getStr:

char *getStr(void) {
    static char wordd[10 + 1];
    ...
    return wordd;
}

또는 힙에 문자열을 할당합니다.

char *getStr(int length) {
    char *wordd = malloc(length + 1);
    ...
    return wordd;
}
char word[length];
char *rtnPtr = word;
...
return rtnPtr;

이것은 좋지 않습니다.자동(범위 지정) 변수로 포인터를 반환하고 있으며, 함수가 반환될 때 포인터는 파기됩니다.포인터는 파괴된 변수를 가리키고 있으며, 이는 거의 확실하게 "이상한" 결과(정의되지 않은 동작)를 생성합니다.

에는 '어울리다'를 .mallocchar *rtnPtr = malloc(length) 、 。free을 몸에 익히다main.

스택에 문자열을 할당한 후 포인터를 반환합니다.함수가 돌아오면 스택 할당은 무효가 됩니다.이 시점에서 포인터는 다음에 함수를 호출했을 때 덮어쓸 가능성이 있는 스택상의 영역을 가리킵니다.

실행하려는 작업을 수행하려면 다음 중 하나를 수행해야 합니다.

  1. 를 사용하여 합니다.malloc이치노 후, 는 「 」, 「 」를 호출할 .free억으기
  2. 호출함수(스트링을 사용하는 기능)의 스택에 스트링을 할당하고, 그 스트링을 넣는 함수에 포인터를 건네줍니다.콜링 함수에의 콜 전체중에, 그 스택상의 데이터는 유효합니다.이 스택에 할당되어 있는 공간을 반환하면, 다른 것에 의해서 사용됩니다.

다른 사람들이 이미 말했듯이, 힙에 할당하지 않고는 비정수 문자열을 유용한 방법으로 반환할 수 없습니다(예를 들어 strdup 사용).그러나 최신 버전의 C 표준(C89 이상)에서는 구조물을 반환할 수 있습니다.결과가 힙에 없기 때문에 호출자가 결과 할당을 해제할 필요는 없습니다.그리고 실타래는 안전해.

#include <stdio.h>

struct stringbuf
{
  char buf[40];
};

struct stringbuf getanswer(int i)
{
  struct stringbuf result = { 0 };

  snprintf(result.buf, sizeof(result.buf), "The answer is %d", i);

  return result;
}

int main(int argc, char **argv)
{
  /*
   * Remember to pass the .buf member, not the struct, to functions
   * such as printf which expect a character pointer as argument!
   * Passing the result of getanswer in the next line without .buf
   * appended, will likely crash the program because the program
   * will put the entire struct on the stack, not a character
   * pointer, and will make printf interpret the first few bytes
   * of the string as a pointer. That would be bad.
   */
  printf("How many arguments did I get? %s\n", getanswer(argc).buf);
  return 0;
}

주의: 샘플 코드를 가능한 한 단순하고 집중적으로 유지하기 위해 typedef를 사용하지 않고 구조 유형을 선언했습니다.typedef를 사용하여 정의된 유형을 반환하면 많은 입력을 절약할 수 있습니다.

몇 가지 단점이 있습니다(분명히).

  • 구조를 반환하는 함수는 NULL을 반환할 수 없습니다.
  • 컴파일러는 컴파일 시 반환 타입의 크기를 알아야 하기 때문에 구조 내의 버퍼 크기는 고정되어 있습니다.
  • 구조체를 반환하는 함수의 결과는 스택에 저장될 수 있습니다.이것은 스택 공간이 많지 않은 소규모 시스템(마이크로 컨트롤러 등)에서 문제가 발생할 수 있습니다.
  • 문자 배열과 달리 구조의 인스턴스는 저장된 문자열에 사용할 수 있는 별칭이 아닙니다.즉, 문자 배열을 만들고 이름을 첫 번째 문자에 대한 포인터로 사용할 수 있지만 구조체의 이름을 포인터로 사용할 수는 없습니다.

문자 배열이 있는 구조는 배열 자체와 같지 않다는 점을 기억해야 하기 때문에 마지막 포인트가 중요합니다.따라서 문자열 함수를 호출하려면 구조체에 대한 포인터가 아니라 문자열 멤버 변수를 전달해야 합니다.이것은 printf나 friends와 같은 다양한 인수를 가진 함수에서 특히 중요합니다.이 함수는 컴파일러가 잘못해도 경고를 하지 않을 수 있습니다.구조를 전달하면 첫 번째 문자에 대한 포인터뿐만 아니라 전체 구조가 스택에 배치됩니다.Printf는 구조체의 처음 몇 글자를 문자 포인터로 해석합니다.이것은 확실히 무효가 됩니다.

네, 구조물에 대한 포인터를 문자 *에 던져 문자열 함수(프린트 f 포함)에 전달하면 올바르게 동작할 수 있지만, 이렇게 하는 것은 좋지 않다고 생각합니다.스트링 버퍼 앞의 구조 선언에 다른 멤버 변수를 넣기로 결정한 경우 스트링 버퍼가 시작되는 곳에서 시작된다고 가정하는 구조물에 대한 타입캐스트포인터를 사용하면 자동으로 실패합니다.이 문제는 피하고 싶기 때문에 다소 불편하더라도 문자열 멤버 변수에 대한 포인터를 사용하십시오.

===제이크

시톤에 대한 이해를 위해 노력하던 중 우연히 이 실마리를 발견했습니다.C/Cython 인터페이스에서 작업하는 다른 사용자에게는 원래 질문의 확장이 유용할 수 있습니다.이것이 원래의 질문의 연장선입니다.C 함수에서 문자열을 반환하여 Cython에서 사용할 수 있도록 하려면 어떻게 해야 합니까?

익숙하지 않은 사용자는 Cython을 사용하여 속도를 높일 필요가 있는 Python 코드를 정적으로 입력할 수 있습니다.이 과정은 Python :)을 쓰는 것을 즐기는 것입니다.이 과정은 다소 느리다는 것을 발견하고 프로파일링하여 한두 개의 함수를 분리하여 사이톤화 합니다.와우. C 속도에 가깝습니다(C로 컴파일됨). 고정.예. 다른 용도는 여기서처럼 Python에 C 함수나 라이브러리를 Import하는 것입니다.

그러면 문자열이 인쇄되고 동일 문자열 또는 다른 문자열이 Python으로 반환됩니다. sayhello sayhelloc, sython sayhello.pyx, sython의 파일이 .를 사용하여 할 때python setup.py build_ext --inplacepython(ipython) ipython(Import) sayhello(sayhello).hello run.

c_hello.c

#include <stdio.h>

char *c_hello() {
  char *mystr = "Hello World!\n";
  return mystr;
  // return "this string";  // alterative
}

안부 전해주세요.플라스틱

cdef extern from "c_hello.c":
    cdef char* c_hello()

def hello():
    return c_hello()

setup.py

from setuptools import setup
from setuptools.extension import Extension
from Cython.Distutils import build_ext
from Cython.Build import cythonize


ext_modules = cythonize([Extension("sayhello", ["sayhello.pyx"])])


setup(
name = 'Hello world app',
cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules
)

포인터가 함수의 로컬 변수를 가리키고 있습니다.기능에서 돌아오자마자 메모리는 할당 해제됩니다.다른 기능에서 사용하려면 힙에 메모리를 할당해야 합니다.

★★char *rtnPtr = word;

일을 char *rtnPtr = malloc(length);

메인 기능으로 사용할 수 있도록 합니다.사용 후 메모리를 해방합니다.

word하며, 「스택」, 「스택」이 되면 .getStr() 하다 정의되지 않은 행동을 .정의되지 않은 동작을 호출하고 있습니다.

보다 쉬운 방법: strdup으로 malloc'd된 문자열에 포인터를 반환합니다.

#include <ncurses.h>

char * getStr(int length)
{   
    char word[length];

    for (int i = 0; i < length; i++)
    {
        word[i] = getch();
    }

    word[i] = '\0';
    return strdup(&word[0]);
}

int main()
{
    char wordd[10];
    initscr();
    *wordd = getStr(10);
    printw("The string is:\n");
    printw("%s\n",*wordd);
    getch();
    endwin();
    return 0;
}

언급URL : https://stackoverflow.com/questions/25798977/returning-string-from-c-function

반응형