Көрсеткішті қалай өтуге және үймеде орын бөлу

Мен функцияға char-таңбалауышын жеткізуге тырысамын, ол содан кейін оны қоңырау функциясы оны пайдалана алатын етіп толтырады. Мен әрдайым қоңырау шалу функциясындағы ғажайып нәрселерді бергенімдей, мен жасаған әрекеттерім туралы қарапайым ұсыныс жасадым:

#include 
#include 

void bla(char *t)
{
    t = (char*) malloc(5);
    if (t != 0) {
        t[0] = 'h';
        printf("%c\n", t[0]);
    }
}

int main(int argc, char **argv)
{
    char b[10];

    bla(b);
    printf("%c\n", b[0]);
    return 1;
}

Мен C дәлелдің көшірмесін өткізетін нәрсе бар ма екеніне сенімді емеспін. Көрсеткішті көрсеткішке қою керек пе немесе сол жақсырақ шешім бар ма?

EDIT:

Кешіріңіздер, бірақ мен оны алмадым. Мына мысалды қарап шығыңыз:

#include 
#include 

void blub(char **t)
{
    printf("%d\n", *t);
    *t = (char*) malloc(sizeof(char) * 5);
    *t[0] = 'a';
    *t[1] = 'b';
    printf("%d\n", *t);
    printf("%d\n", *t[0]);
    printf("%d\n", *t[1]);
}

int main(int argc, char **argv)
{
    char *a;
    blub(&a);
    printf("%d\n", a);
    printf("%d\n", a[0]);
    printf("%d\n", a[1]);

    return 1;
}

Шығару келесідей:

./main
6154128
140488712
97
98
140488712
97
0      <== THIS SHOULD BE 98 AS ABOVE!?

Неліктен 98 blafu функциясында аламын, ал бастысы - нөлдік көрсеткіш ?! Мен толықтай шатастырамын: /

0
@pluckyDuck - менің редакциямды қараңыз :) Сіз дұрыс лакшамен отырсыз.
қосылды автор Kiril Kirov, көзі
бұл код мағынасы аз ...
қосылды автор Mitch Wheat, көзі
Жадты бір жерден босатуды ұмытпаңыз!
қосылды автор Nick, көзі

6 жауаптар

Көрсеткішті меңзермен пайдалану керек.

//............vv
void bla(char **t)

Содан кейін меңзерді оны ажырату арқылы пайдаланыңыз:

// note the '*' in front of t
*t = (char*) malloc(5);
if (*t != 0) {
    *t[0] = 'h';
    printf("%c\n", *t[0]);
}

Сондай-ақ, b ретінде char b [10] ретінде емес, char * ретінде хабарлаңыз.


Неліктен? Сіз көрсеткішті өзгерткіңіз келгендіктен. Логика басқа түрлермен бірдей, бірақ мұнда бір-ақ шатастыруға болады Бұл туралы ойланыңыз: Егер int өту керек болса және оны өзгерту қажет болса, көрсеткішті керек. көрсеткішті char үшін өту керек және оны өзгерту қажет, сондықтан « сілтегішті сілтегішті пайдаланыңыз« :)


EDIT: According to your edit - yes, you have understood this perfectly, there's just a small problem - the priority of operator* and operator[]. If you replace your *t[X] with (*t)[X], everythng will be fine :)

7
қосылды
сен менің өмірімді сақтадыңыз :)
қосылды автор pluckyDuck, көзі

Көрсеткішке көрсеткішті қолдансаңыз

void blah(char **t)

сіз malloc ретінде жадты (баста) тағайындауға болады

*t = malloc(size);

және сіз былай дейді:

char *b;
bla(&b);

және оны бланкпен бөлуге және толтыруға болады және нәтиже негізгі түрде басып шығарылуы мүмкін.

2
қосылды

Сіз жұмыс істейтін көрсеткішті жібердіңіз. Осының арқасында сіз функцияға нақты көшірілген көшірменің көмегімен ғана өзгерте аласыз (функция қайтарылғаннан кейін), тек ол көрсететін нысанды өзгерте аласыз. Функциядағы барлық өзгерістер көрсеткіштің көшірмесінде жасалады. Функция қайтарылған кезде оның бастапқы мәні өзгеріссіз қалады.

(1) Кейбір айнымалы функцияны кейбір функцияда өзгерткіңіз келсе, оған сілтегішті беру керек. Егер бұл айнымалы көрсеткіш түрі болса, онда меңзерді көрсеткішке бағыттаңыз - көрсеткішке көрсеткіш! Сіздің жағдайда, бұл айнымалылар type ** түрінде болады.

(2) Егер функциядағы жинақты жадқа бөлгіңіз келсе, стаканы пайдаланудың қажеті жоқ - b * белгішесін char * деп жариялаңыз.

(3) Хабаны жадқа бөлгеннен кейін оны бөліп алуды ұмытпаңыз, әйтпесе жадыдағы ағып кетулеріңізге жол бересіз.

(4) Қате болмаса, сіздің өтініміңізден 0 қайтарыңыз. Басқа қайтарылған мәндерді сақтаңыз қате кодтары үшін - сіздің қолданбаңызда орын алуы мүмкін түрлі қателіктер туындаған жағдайда әртүрлі кодтарды қайтарыңыз.

The final point is that this is a pure C application. In C++ you would use new/delete to allocate/deallocate memory, std::string instead of char* for strings, and std::cout << instead of printf for sending text to the output stream

void bla(char **pt)              //(1)
{
    *pt = (char*)malloc(5);

    if (*pt != 0) 
    {
        *pt[0] = 'h';
        printf("%c\n", *pt[0]);
    }
}

int main(int argc, char **argv)
{
    char* b = 0;                 //(2)

    bla(&b);
    printf("%c\n", b[0]);

    if(b)
    {
        free(b);                 //(3)
        b = 0;
    }

    return 0;                    //(4)
}
1
қосылды

Егер нәтижені var сілтемесі арқылы қайтарғыңыз келсе, онда иә, көрсеткішке көрсеткішті беру керек (немесе әдеттегідей нәтижені қайтару үшін char * bla ()). Null terminators ұмытпаңыз!

0
қосылды

char b [10]; жазған кезде, сізде статистикалық бөлінген массив бар, оған қосымша бос орын қажет емес, ол 10 char мәндері.

Егер сіз функцияны сол жиымның мазмұнын өзгертуге рұқсат бергіңіз келсе, оны қарапайым көрсеткіштен орындаңыз (бірақ бөлектеместен!):

void bla(char *t)
{
    if (t != 0) {
        t[0] = 'h';
        printf("%c\n", t[0]);
    }
}

Функциядан кейін, main b мәні де өзгереді.

0
қосылды
бұл нақты проблеманың үлгісі ғана және ол malloc пайдалану керек.
қосылды автор pluckyDuck, көзі

Екінші мысалдағы елдің мінез-құлқының себебі - операторлардың басымдығы. [] (Кращтар, жиым әріпсандары) * (ауысу)

So, *t[1] is the same as *(t[1]). You need (*t)[1]

t - таңбалауышқа көрсеткіш болып табылады:

*(t[1]) means "take t's address, go (sizeof(char*)) bytes ahead, dereference the address, and dereference again"

(*t)[1] means "take t's address, dereference it, go (sizeof(char)) bytes ahead and dereference again"

Шын мәнінде, бірінші жағдайда мінез-құлықсыз анықталмайды, өйткені ол т-дан кейінгі орынды екі есе көбейтуге тырысады. Сіздің мысалыңызда бірінші мән әрқашан басып шығарылады, себебі [0] тек қана ауыспалы мәнді білдіреді, сондықтан екі жағдай бірдей болады.

0
қосылды