присвоение массивов указателям в C - PullRequest
0 голосов
/ 28 декабря 2018

Фрагмент 1:

char** x;
char arr[][4] = {"abc","def"};
x = arr;                             // why is this wrong ? but;

Фрагмент 2:

char* x;
char arr[4] = {"def"};
x = arr;                             // this is correct

Так, как мы можем назначить 2d массив двойному указателю (также для любых многомерных массивов)?

Кроме того, у меня есть структура, и я хочу сделать назначение следующим образом:

struct document
{
    char **text;
    int numOfLines;
};

char arr[3][50] = {
    "IF WE COULD TAKE THE TIME",
    "TO LAY IT ON THE LINE",
    "I COULD REST MY HEAD" };
t->text = arr;                           // I think it is the same problem

, но мы можем напрямую назначить двойной указатель как:

t->text = { "IF WE COULD TAKE THE TIME", "TO LAY IT ON THE LINE", "I COULD REST MY HEAD" };

Также почему эторабота:

char *arr[3] = {
    "IF WE COULD TAKE THE TIME",
    "TO LAY IT ON THE LINE",
    "I COULD REST MY HEAD" };
t->text = arr;

Ответы [ 2 ]

0 голосов
/ 28 декабря 2018

Вопрос 1

char arr[][4] = {"abc","def"}; определяет arr как массив массивов.С другими объектами, такими как структура, одна структура, скажем, C, может быть назначена другой структуре, скажем, B, того же типа, используя B = C;.Однако в C есть специальные правила для массивов.

Когда в выражении используется массив, он автоматически преобразуется в указатель на свой первый элемент, за исключением случаев, когда он является операндом sizeof или унарным & или строковый литерал, используемый для инициализации массива.Итак, когда мы пишем:

x = arr;

, автоматическое преобразование делает это так, как если бы мы написали:

x = &arr[0];

Тогда, поскольку &arr[0] является указателем на массив из 4 char, x также должен быть указателем на массив 4 char (или чем-то совместимым, возможно, указателем на массив с неизвестным числом char).

Обратите внимание, что char **x; объявляет указатель на указатель.То есть это указатель, и в памяти, на которую он указывает, должен быть другой указатель.Напротив, &arr[0] является указателем на массив.Это указатель, и в памяти, на которую он указывает, имеется массив 4 char.Если вы попытаетесь использовать **x, компилятор будет искать память, на которую указывает x, и ожидать, что там найдется указатель.Если вместо этого есть не указатель, а четыре произвольных значения char, программа будет прервана.Так что char **x несовместимо с указателем на массив 4 char.

. Правильное объявление для x будет char (*x)[4];.После такого объявления присваивание x = arr; будет правильным.

Вопрос 2

Ваш код t->text = { "IF WE COULD TAKE THE TIME", "TO LAY IT ON THE LINE", "I COULD REST MY HEAD" }; не строго соответствует C и не компилируется в типичных компиляторах.

Вопрос 3

Рассмотрим код (отрегулированный для разрешения компиляции):

struct document
{
    char **text;
    int numOfLines;
} t;

char *arr[3] = {
    "IF WE COULD TAKE THE TIME",
    "TO LAY IT ON THE LINE",
    "I COULD REST MY HEAD" };
t.text = arr;

char *arr[3] объявляет arr массивом из 3 указателей на char.Затем он инициализируется, чтобы содержать три указателя на (первые символы) строк.

Таким образом, каждый элемент arr, arr[i] является указателем на char.По правилу C об автоматическом преобразовании массивов, в t.text = arr;, arr преобразуется в указатель на свой первый элемент.Итак, у нас есть t.text = &arr[0];.Тогда &arr[0] - указатель на указатель на char, а t.text - указатель на указатель на char, поэтому типы совместимы.

0 голосов
/ 28 декабря 2018

Оператор char **x; означает указатель на указатель, но char arr[][4]; - это указатель на массив.Код ниже работает.

#include <stdio.h>

int main(void)
{   
    char (*x)[10];
    char arr1[][10] = {{"First"}, {"Second"}};
    x = arr1;
    printf("%s\n%s\n", arr1[0], arr1[1]);
    printf("%s\n%s\n", x[0], x[1]);
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...