Могу ли я создать массив из Char указателей в C?

Я новичок в C, и в C все по-другому, чем на любом другом языке, который я узнал. В моей домашней работе я хочу создать массив символов, которые указывают на массив символов, но вместо того, чтобы создавать многомерный массив char, я полагаю, что у меня будет больше возможностей управления и создания массивов char и поместить каждый отдельный индексы исходного массива char:

char keywords[10];
keywords[0] = "float";

Приведенный выше пример - это прояснить и простой случай. Но мой вопрос связан с исследованиями, которые я делал, и я чем-то смущен. Обычно это будет работать на других языках, но в C это будет:

char *keyword[10];
keywords[0] = "float";

Но когда я хочу отправить его через функцию, почему это необходимо:

void function(char **keyword); //function prototype

Не хватило бы просто передать указатель массива?

Ответ 1

Похоже, вы смущены двойными звездами в

void function(char ** keyword);

Двойные звезды просто означают, что эта функция ожидает, что вы передадите указатель на указатель на char. Этот синтаксис не содержит никакой информации о том, что вы используете массив, или что char на самом деле является первым char для многих в строке. Для вас, как программиста, знать, какую структуру данных это char ** на самом деле указывает.

Например, пусть предположим, что начало вашего массива хранится по адресу 0x1000. Аргумент keyword функции должен иметь значение 0x1000. Если вы разыскиваете keyword, вы получите первую запись в массиве, которая представляет собой char *, которая указывает на первый char в строке "float". Если вы разыщите char *, вы получите char "f".

Код (надуманный) для этого будет выглядеть так:

void function(char **keyword)
{
    char * first_string = *keyword;   // *keyword is equivalent to keyword[0]
    char first_char = *first_string;  // *first_string is equivalent to first_string[0]
}

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

Ответ 2

char *keyword[10];

keyword - это массив 10 из char *. В контексте значения он преобразуется в указатель на char *.

Это преобразование является частью того, что Крис Торек называет "Правило" :

"Как отмечено в другом месте, C имеет очень важное правило о массивах и указателях. Это правило - правило - говорит, что в контексте значений объект типа" массив T становится указателем типа типа "to T, указывая на первый элемент этого массива"

См. здесь для получения дополнительной информации: http://web.torek.net/torek/c/pa.html

В C-FAQ также есть запись в этом массиве для преобразования указателя:

Вопрос 6.3: Итак, что подразумевается под "эквивалентностью указателей и массивов" в C?

http://c-faq.com/aryptr/aryptrequiv.html

Ответ 3

Если вы хотите

void function(char **keyword);

Энди, подумайте, что массив - это просто указатель (к началу массива), вот почему вы пишете:

void function(char **keyword);

Поскольку вы создали массив для указателей char.

Если это проще понять, попробуйте:

void function(char *keyword[]);

Но это больше C-стандарт для использования первого, хотя, если вы используете компилятор С++, это не имеет большого значения.

Ответ 4

Вот ответ.

#include<stdio.h>

int main(void)
{
        char *CharPtr[3];
        char a[4]="abc";
        char b[4]="def";
        char c[4]="ghi";
        CharPtr[0]=a;
        CharPtr[1]=b;
        CharPtr[2]=c;

        printf("\n content of CharPtr[0] =%s",CharPtr[0]);
        printf("\n content of CharPtr[1] =%s",CharPtr[1]);
        printf("\n content of CharPtr[2] =%s\n",CharPtr[2]);

        printf(" \n content of char a[4]=%s",a);
        printf(" \n content of char b[4]=%s",b);
        printf(" \n content of char c[4]=%s\n",c);
}

Ответ 5

В C вы не можете передать массив функции. Вместо этого вы передаете указатель на начало массива. Поскольку у вас есть массив char*, функция получит указатель на char*, который равен char**.

Если вы хотите, вы можете записать (в прототипе) char *keyword[] вместо char **keyword. Компилятор автоматически преобразует его.

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

Ответ 6

char *keywords[10] - массив указателей символов. Итак, keywords[0], keywords[1].. и т.д. Будут иметь адреса для разных массивов символов.

В printf вы можете использовать %s и keywords[0] для печати всего массива символов, адрес которого (то есть адрес первого байта в массиве) сохраняется в keywords[0].

При переходе к функции, если вы даете *keywords, вы ссылаетесь на значение в (адрес, хранящийся в keywords[0]), который снова является адресом. Таким образом, чтобы получить значение вместо адреса, вы можете добавить еще один *... Надеюсь, что немного разъясняется.

Ответ 7

Я предполагаю, что вы назначаете свою первую строку:

"float"

в первую позицию индекса ключевого слова [0]

char keyword[0] = "float";

которая является первой позицией индекса массива:

char keyword[10];

Если это так, то в некотором смысле вы создаете структуру данных, которая содержит структуру данных. Массив любого типа является "наименьшей" структурой данных этого типа в C. Учитывая, что в вашем примере вы создаете массив символов, вы фактически используете наименьший тип данных (char= 1 бит) в каждой позиции индекса самой маленькой встроенной структуры данных (массив).

С учетом сказанного, если в вашем примере вы пытаетесь создать массив массивов; ваш массив символов

/* Hold ten characters total */
char keyword[10];  

предназначен для размещения 10 символов. Один в каждой позиции индекса (что вы, наверное, уже знаете). Итак, после объявления ключевого слова массива, вы затем попытаетесь инициализировать первую позицию индекса массива с помощью другого (второго) символьного массива:

/* I believe this is what you had stated */
char keywords[0] = "float";

Со вторым массивом символов, имеющим индекс из 5 позиций по размеру.

Чтобы достичь желаемой цели, вы, по существу, создаете массив, который в основном эмулирует влияние структуры данных, которая "удерживает" другие структуры данных.

ПРИМЕЧАНИЕ. Если у вас были/были планы по созданию структуры данных, которая содержит структуру данных, которая содержит структуру данных. А.К.А. тройная вложенная структура данных, и в этом случае я думаю, что это была бы матрица, КОТОРЫЙ Я НЕ РЕКОМЕНДУЕТ!

Тем не менее, матричная структура будет иметь форму первой позиции индекса ключевого слова, которому присваивается весь массив ключевых слов, который будет включать все данные, хранящиеся в каждой позиции индекса в массиве ключевых слов. Тогда было бы что-то вроде: keywords1, keywords2,... keywords9,

который по существу будет эмулировать форму:

char *keyword[10] = { 
                        char *keywords0[10] = {"float", etc, etc, etc.};
                        char *keywords1[10] = {"keyword1", "secondIndexOfThisArray", etc, etc, etc.}; 
                       and so

                   };

Итак, в основном справа налево, массив ключевых слов - это массив указателей, который указывает на массив указателей, указывающий на массивы символов.

Если это то, что вы представляете, вам лучше определить тип данных для персонализации структуры/записи, и в этой настраиваемой структуре вы захотите определить подчиненный или дочерний уровень структур. Вы также можете предварительно объявить их, а затем инициализировать их.

например.

typedef *nestedDataStructures {

    struct keyWords[];
    struct keyWords1[];
    struct keyWords2[];

    ... and so on.
}; nestedDataStructures

Вместо того, чтобы добавить десять структур в одну настраиваемую структуру, я бы разбил на 3 или 4 (как это бывает во многих структурах и использует) и создаст модуль для создания симметричных уровней абстракции при управлении вашим набором данных.

Тем не менее, вы не можете создать массив символов и потенциально назначить другой массив символов таким образом, который вы сделали (или кто знает, может быть, вы можете), но так, как вы хотели бы эмулировать массив, содержащий массивы, состоит в том, чтобы создать массив указателей символов впереди, по номерам индексов X-номера и затем инициализировать, затем использовать массивы символов в форме строк, объявленных с инициализацией исходного объявления.

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

Например, вы всегда можете сделать что-то вроде этого:

/* Example of the program and declaration with out a function */
#include <stdio.h>

int main(){

    /* 
     * A character pointer array that contains multiple 
     * character arrays.
     */

    char *grewMe[2] = {"I want to ", "grow to be bigger"};

    int w = 0;

    for(; w < 2;) {
        printf("%s", grewMe[w]);
        ++w;
    }

    printf(" :-)\n");
    w = 0;
    return 0;
}
// Output:
// I want to grow to be bigger :-)

Или что-то вроде этого:

/* Example of program: function passed arguments 
 * of a pointer to the array of pointers 
 */
#include <stdio.h>

void mygrowth(char *growMe[]);

int main(){

    char *growMe[2] = {"I want to ", "grow to be bigger"};

    mygrowth(growMe);  
    printf(" :-)\n");

    return 0;

}
void mygrowth(char *growMe[])
{

    int w = 0;
    for (; w < 2;) {
        printf("%s", growMe[w]);
        ++w;
    } 
}

Назначение каждой позиции индекса при ее передаче в качестве аргумента:

/* 
 * This program compiles, runs and outputs properly
 * Example of a program with a function of 
 * arguments pnt2pnter 
 */

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

void thoughtAsAFunction(char **iThink);

int main()
{

    char *iThink[10] = {"I am trying to grow, but it a hard task to ",
                        "accomplish. My father is short ", 
                        "my mother is even shorter than him, ", 
                        "what is the probability of me getting taller? ", 
                        "Well both my grandfather were Six ",
                        "Foot Five, and both my grandmother ", 
                        "were over 5 foot 8 inches tall! If my ",  
                        "grandparent genes point to my parents, and my ", 
                        "parent genes point to mine I might have a chance ",
                        "of being 6 foot. Do you know what I mean? "};

    thoughtAsAFunction(iThink);

    printf(":-)\n");

    return 0;
}
void thoughtAsAFunction(char **iThink) {

    int andy = 0;
    for (; andy < 10;) {
        char * pntThroughPnt = iThink[andy];
        printf("%s", pntThroughPnt);
        ++andy;
    }
    andy = 0;
}

Или передайте по ссылке с приращением переменной count цикла:

/*
 * This program compiles, runs, and outputs all of the character
 * arrays. 
 * 
 */
#include <stdio.h>
#include <stdlib.h>

void thoughtAsAFunction(char **iThink);

int main()
{

    char *iThink[10] = {"I am trying to grow, but it a hard task to ",
                        "accomplish. My father is short ", 
                        "my mother is even shorter than him, ", 
                        "what is the probability of me getting taller? ", 
                        "Well both my grandfather were Six ",
                        "Foot Five, and both my grandmother ", 
                        "were over 5 foot 8 inches tall! If my ",  
                        "grandparent genes point to my parents, and my ", 
                        "parent genes point to mine, then I might have a chance ",
                        "of being 6 foot. Do you know what I mean? "};

    int andy = 0;
    for (; andy < 10;) {
        // pass by reference and increment.
        thoughtAsAFunction(&iThink[andy]);
        ++andy;

    }

    printf(":-)\n");
    andy = 0;

    return 0;
}
void thoughtAsAFunction(char **iThink) {

    char * pntThroughPnt = *iThink;
    printf("%s", pntThroughPnt);

}

Имейте в виду, что это так, если вы объявляете массив указателей (char * array [10];), и каждый указатель указывает на массив символов.