Как написать в char * из функции в C - PullRequest
0 голосов
/ 24 сентября 2019

Я изо всех сил пытаюсь написать символ *, переданный в качестве аргумента.Я хочу написать строку в char * из функции write_char ().С приведенным ниже кодом, я получаю ошибку сегментации.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void write_char(char* c){
    c = (char*)malloc(11*(sizeof(char)));
    c = "some string";
}

int main(){
    char* test_char;
    write_char(test_char);
    printf("%s", test_char);

    return 0;
}

Ответы [ 5 ]

8 голосов
/ 24 сентября 2019

У вас есть две проблемы (связанные с тем, что вы пытаетесь сделать, есть и другие проблемы):

  1. Аргументы в C передаются по значению,это означает, что переменная аргумента (c в вашей функции write_char) является копией значения из test_char в функции main.Изменение этой копии (например, присвоение ей) приведет только к изменению значения локальных переменных, а не исходного значения переменных.

  2. При назначении переменной во второй раз текущее значение переменной будет перезаписано.Если вы сделаете, например,

    int a;
    a = 5;
    a = 10;
    

    , вы (надеюсь) не удивитесь, почему значение a было изменено на 10 во втором назначении.То, что переменная является указателем, не меняет эту семантику.


Теперь, как решить вашу проблему ... Первая проблема может быть легко решена с помощью функции вернуть указатель вместо этого.И вторая проблема может быть решена путем копирования строки в память вместо переназначения указателя.

Поэтому я предлагаю вам написать что-то вроде

char *get_string(void)
{
    char *ptr = malloc(strlen("some string") + 1);  // Allocate memory, +1 for terminator
    strcpy(ptr, "some string");  // Copy some data into the allocated memory
    return ptr;  // Return the pointer
}

Это может быть использовано как

char *test_string = get_string();
printf("My string is %s\n", test_string);
free(test_string);  // Remember to free the memory we have allocated
2 голосов
/ 24 сентября 2019

В функции

void write_char(char* c){
    c = (char*)malloc(11*(sizeof(char)));
    c = "some string";
}

параметр c является локальной переменной функции.Изменение его в функции не влияет на исходный аргумент, поскольку он передается по значению.То есть функция имеет дело с копией исходного аргумента.

Вы должны передать аргумент по ссылке через указатель на него.

Также функция имеет утечку памяти, потому что сначала указательбыл назначен адрес выделенной памяти, а затем переназначен с адресом первого символа строкового литерала "some string".

Если вы хотите создать копию строкового литерала, то вам нужноследующий

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void write_char( char **s )
{
    const char *literal = "some string";
    *s = malloc( strlen( literal ) + 1 );

    if ( *s ) strcpy( *s, literal );
}

int main( void )
{
    char *test_char = NULL;

    write_char( &test_char );

    if ( test_char ) puts( test_char );

    free( test_char );
}    

Вывод программы:

some string

Не забудьте динамически выделить массив символов, достаточно большой для хранения также конечного нуля строкового литерала.

И вы должны освободить выделенную память, когда выделенный массив больше не нужен.

Если вы хотите просто инициализировать указатель с адресом строкового литерала, тогда нет необходимости выделять динамически память.

Вы можете написать

#include <stdio.h>

void write_char( char **s )
{
    *s = "some string";
}

int main( void )
{
    char *test_char = NULL;

    write_char( &test_char );

    puts( test_char );
}    
0 голосов
/ 24 сентября 2019

Назначение строк в C очень отличается от большинства современных языков.Если вы объявляете char * и назначаете строку в том же операторе, например,

char *c = "some string";

, которая работает нормально, так как компилятор может решить, сколько памяти выделить для этой строки.Однако после этого вам не следует менять значение строки на =, так как это в основном используется для константной строки.Если вы хотите сделать это особенно ясным, объявите это с const.Вам нужно будет использовать strcpy.Даже тогда вы захотите не объявлять большинство строк с помощью заданной строки, как я уже делал выше, если вы планируете изменить ее.Вот пример этого:

char *c;
c = malloc(16 * sizeof(char));
strcpy(c, "Hello, world\n");

Если вы передаете указатель на функцию, которая будет перераспределять его, или даже malloc в первую очередь, вам понадобится указатель на указательиначе строка в main не изменится.

void myfunc(char **c) {
    char *tmp = realloc(*c, 32 * sizeof(char));
    if(tmp != NULL) {
        *c = tmp;
    }
}

char *c = malloc(16 * sizeof(char));
strcpy(c, "Hello, world\n");
myfunc(&c);
0 голосов
/ 24 сентября 2019
char* test_char="string"; // initialize string at the time of declaration


void write_char(char* c){
    c = (char*)malloc(11*(sizeof(char)));

}

int main(){
    char* test_char="strin";
    write_char(test_char);
    printf("%s", test_char);

    return 0;
}
0 голосов
/ 24 сентября 2019

В C вам нужно передать указатель на указатель.Ваш вызов malloc пытается изменить значение передаваемой переменной, но на самом деле это всего лишь копия.Вещественная переменная, которую вы передаете, не изменится.

Кроме того, способ, которым вы копируете строку в символ *, не использует присваивание ... Вот несколько исправленных кодов:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

void write_char(char** c){
    size_t len = strlen("some string");
    *c = (char*)malloc(len + 1); // + 1 for null termination
    strncpy(*c, "some string", len);
}

int main(){
    char* test_char;
    write_char(&test_char);
    printf("%s", test_char);

    return 0;
}
...