programing

새 문자열 값을 올바르게 할당하려면 어떻게 해야 합니까?

kingscode 2022. 7. 11. 23:19
반응형

새 문자열 값을 올바르게 할당하려면 어떻게 해야 합니까?

저는 C의 이 사소한 문제를 가장 깔끔하고 안전한 방법으로 해결하는 방법을 이해하려고 합니다.예를 들어 보겠습니다.

#include <stdio.h>

int main(int argc, char *argv[])
{
    typedef struct
    {
        char name[20];
        char surname[20];
        int unsigned age;
    } person;

    // Here I can pass strings as values...how does it work?
    person p = {"John", "Doe", 30};

    printf("Name: %s; Age: %d\n", p.name, p.age);

    // This works as expected...
    p.age = 25;

    //...but the same approach doesn't work with a string
    p.name = "Jane";

    printf("Name: %s; Age: %d\n", p.name, p.age);

    return 1;
}

컴파일러 오류:

main.c: 함수 'main'에서: main.c:18: 오류: 유형 'char *'에서 유형 'char[20]'에 할당할 때 호환되지 않는 유형

C(C++가 아님)에는 String 타입이 없고 대신 C++의 배열을 사용하는 것으로 알고 있습니다.chars, 그래서 이것을 하는 또 다른 방법은 예시 구조를 변경하여 포인터를 유지하는 것입니다.chars:

#include <stdio.h>

int main(int argc, char *argv[])
{
    typedef struct
    {
        char *name;
        char *surname;
        int unsigned age;
    } person;

    person p = {"John", "Doe", 30};

    printf("Name: %s; Age: %d\n", p.name, p.age);

    p.age = 25;

    p.name = "Jane";

    printf("Name: %s; Age: %d\n", p.name, p.age);

    return 1;
}

이것은 예상대로 됩니다만, 더 좋은 방법이 없을까요?

첫 번째 예는 배열에 값을 할당할 수 없기 때문에 작동하지 않습니다.배열은 이 점에서 const pointer와 같이 동작합니다.다만, 새로운 값을 어레이에 카피할 수 있습니다.

strcpy(p.name, "Jane");

문자 배열은 문자열의 최대 크기를 미리 알고 있는 경우 사용할 수 있습니다.예를 들어 첫 번째 예에서는 이름이 19자 안에 들어가는 것을 100% 확신할 수 있습니다(종료 0 값을 저장하기 위해서는 항상 한 문자가 필요하므로 20자가 아닙니다).

반대로 가능한 최대 문자열 크기를 모르거나 메모리 사용을 최적화하려면 포인터가 더 좋습니다. 예를 들어 "John" 이름에 512자를 예약하지 마십시오.단, 포인터를 사용하면 포인터가 가리키는 버퍼를 동적으로 할당하고 더 이상 필요하지 않을 때 해방하여 메모리 누수를 방지해야 합니다.

업데이트: 동적으로 할당된 버퍼의 예(두 번째 예시의 구조 정의를 사용):

char* firstName = "Johnnie";
char* surname = "B. Goode";
person p;

p.name = malloc(strlen(firstName) + 1);
p.surname = malloc(strlen(surname) + 1);

p.age = 25;
strcpy(p.name, firstName);
strcpy(p.surname, surname);

printf("Name: %s; Age: %d\n",p.name,p.age);

free(p.surname);
free(p.name);

문자열은 추상 객체, char 배열은 컨테이너로 간주합니다.문자열은 임의의 크기를 사용할 수 있지만 컨테이너는 문자열 길이보다 적어도1 이상 커야 합니다(늘 터미네이터를 보관 유지).

C는 문자열에 대한 구문 지원이 거의 없습니다.문자열 연산자는 없습니다(char-array 연산자와 char-pointer 연산자만).문자열을 할당할 수 없습니다.

하지만 함수를 호출하여 원하는 것을 달성할 수 있습니다.

strncpy()여기서 기능을 사용할 수 있습니다.최대한의 안전을 위해 다음 패턴을 따르는 것이 좋습니다.

strncpy(p.name, "Jane", 19);
p.name[19] = '\0'; //add null terminator just in case

또, 이 비디오의strncat()그리고.memcpy()기능들.

그 두 구조는 다르다.첫 번째 구조를 초기화하면 약 40바이트의 메모리가 할당됩니다.두 번째 구조를 초기화하면 약 10바이트의 메모리가 할당됩니다.(실제 양은 아키텍처에 따라 다름)

문자열 리터럴(문자열 상수)을 사용하여 문자 배열을 초기화할 수 있습니다.이래서

Person p = {"John", "Doe",30};

첫 번째 예에서는 동작합니다.

C에서는 (기존의 의미로) 문자열을 할당할 수 없습니다.

가지고 있는 문자열 리터럴("John")은 코드가 실행될 때 메모리에 로드됩니다.이러한 리터럴 중 하나를 사용하여 어레이를 초기화하면 문자열이 새 메모리 위치에 복사됩니다.두 번째 예에서는 단순히 문자열 리터럴(위치)에 포인터를 복사하고 있습니다.다음과 같은 작업을 수행합니다.

char* string = "Hello";
*string = 'C'

컴파일 오류 또는 런타임 오류를 일으킬 수 있습니다(잘 모르겠습니다).리터럴 문자열 "Hello"를 수정하고 있기 때문에 이는 잘못된 생각입니다.예를 들어 마이크로컨트롤러에서는 읽기 전용 메모리에 배치될 수 있습니다.

언급URL : https://stackoverflow.com/questions/3131319/how-can-i-correctly-assign-a-new-string-value

반응형