символ [1024] по сравнению с символом *

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

void *HashSetLookup(hashset *h, const void *elemAddr);

который я должен использовать для поиска в наборе хеша, чтобы видеть, существует ли элемент уже там (хеш, и сравните, функции являются частью hashset структуры). В этом случае я использую hashset для хранения указателей на струны до, или более конкретно (символ * *). Моя проблема состоит в том, что следующий код дает отказ сегментации:

    char word[1024];
    /* Some code that writes to the word buffer */
    HashSetLookup(stopList, &word);

в то время как этот код хорошо работает (и как ожидалось):

    char word[1024];
    /* The same code as before that writes to the word buffer */
    char* tmp = strdup(word);
    HashSetLookup(stopList, &tmp);
    free(tmp);

Я думал, что символьное слово [] и символ* было в основном тем же самым. Так как единственной разницей является тот символьный Word [1024], находится в стеке с фиксированной длиной 1 024, но tmp в "куче", занимающей только столько же пространства по мере необходимости (strlen (Word) +1).

Поэтому я не понимаю, почему я должен сделать копию строки в "куче", чтобы смочь вызвать эту функцию. Почему это происходит? Есть ли некоторое более принципиальное различие между символом* tmp = strdup ("что-то") и символьным Word [1024] = "что-то"?

5
задан Siggi 4 July 2010 в 19:41
поделиться

5 ответов

Вы упоминаете, что вам нужен char ** и здесь кроется проблема: для массива, word и &word означают одно и то же - фактическое расположение содержимого массива. Когда вы используете указатель, это работает потому, что "указатель" хранится в другом месте, а указывает на тот же массив. Вам не нужен strdup, вам просто нужно создать указатель:

char* tmp = word;
HashSetLookup(stopList, &tmp);
6
ответ дан 14 December 2019 в 08:40
поделиться

Трудно сказать без документации по HashSetLookup.

Но он ожидает const void * в качестве второго параметра, поэтому вы должны передать tmp, а не &tmp, потому что tmp уже является указателем.

Я вообще не вижу здесь необходимости в char **.

Также, возможно, вам будет интересно узнать, что возвращает HashSetLookup().

1
ответ дан 14 December 2019 в 08:40
поделиться

Вы, должно быть, что-то упустили в первом примере, потому что "слово" вообще не используется.

Так или иначе, в большинстве сред, когда вы пишете 'char *s = "Hello World"', он создается в сегменте кода и не может быть изменен. Сегмент кода означает, что это часть исполняемого кода, который нельзя изменять, а только читать. Когда вы пытаетесь записать его, вы получаете ошибку seg fault.

Однако 'char[]' создается в сегменте данных, поэтому он может быть изменен без проблем.

0
ответ дан 14 December 2019 в 08:40
поделиться
0
ответ дан 14 December 2019 в 08:40
поделиться

Поскольку вы упомянули char ** , я думаю, проблема в том, что функция пытается записать в место, указанное вторым аргументом, то есть когда вы пишете:

HashSetLookup( stopList, &word );

он пытается присвоить адрес слову (и поэтому ему нужен его адрес .), которое перезаписывает буфер указателем.

Это демонстрирует следующий глупый фрагмент (имейте в виду, что адрес массива по-прежнему является адресом его первого элемента):

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

void func( void* boo )
{
        char** ptr = ( char** )boo;
        printf( "func: got %p\n", boo );
        *ptr = "bad func";
}

int main( int argc, char* argv[] )
{
        char buf[128], *p;
        func( &buf ); /* buf got overwritten */
        printf( "array: %s\n", buf );
        p = malloc( 128 );
        func( &p ); /* p got new value */
        printf( "malloc: %s\n", p );
        return 0;
}
0
ответ дан 14 December 2019 в 08:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: