anonymous@RULINUX.NET~# Last login: 2024-12-26 11:16:42
Регистрация Вход Новости | Разметка | Пользователи | Галерея | Форум | Статьи | Неподтвержденное | Трекер | Правила форума | F.A.Q. | Ссылки | Поиск
[#] [Добавить метку] [Редактировать]
Скрыть

[C] Указатель на указатель на ...

Что-то я запутался. С одномерными массивами всё понятно: имя массива есть указатель на его первый элемент. Работа со строками вполне себе понятна. Пример:

c
#include

char str[] = "Привет, лорэнг!";

void output (char *msg)
{
        printf("%s\n",msg);
}

int main (void)
{
        char *tmp;
        tmp = str;
        output(tmp);
        return 0;
}
 

Компилируется без ошибок и предупреждений. И даже работает, как ожидалось. Присвоение (tmp = str) работает. Но стоит перейти к двумерным массивам, как получается уже что-то непонятное. Пример:

c
#include

char str[][8] = {{"Привет,"},{"лорэнг!"}};

void output (char **msg)
{
        int n;
        for(n = 0; n < 1; n++)
                printf("%s\n",msg[n]);
}

int main (void)
{
        char **tmp;
        tmp = str;
        output(str);
        return 0;
}
 

Сразу же при компиляции выскакивает предупреждение:

  1.  >gcc test-2d.c -o test-2d
  2.  test-2d.c: В функции 'main'
  3.  test-2d.c:15: предупреждение: assignment from incompatible pointer type
  4.  test-2d.c:16: предупреждение: passing argument 1 of 'output' from incompatible

Сразу же ругается на присвоение (tmp = str, строка 15) и на передачу в функцию (строка 16), а при запуске программы получаю:

  1.  >./test-2d
  2.  Ошибка сегментирования

А вопрос мой, собственно, и состоит в том, как работать с двумерными массивами через указатели. У меня есть два двумерных массива и я хочу передавать в функцию указатель на один их них.

anonymous(*) (2011-04-19 21:02:00)

[Ответить на это сообщение]
[#] [Добавить метку] [Редактировать] Ответ на: [C] Указатель на указатель на ... от anonymous 2011-04-19 21:02:00
avatar
Скрыть

Re: [C] Указатель на указатель на ...

Попробуй заменить "**" на "*" во втором примере

anonymous(*)(2011-04-19 21:10:01)

[#] [Добавить метку] [Редактировать] Ответ на: Re: [C] Указатель на указатель на ... от anonymous 2011-04-19 21:10:01
avatar
Скрыть

Re: [C] Указатель на указатель на ...

> Попробуй заменить "**" на "*" во втором примере
Так это будет указатель на одномерный массив. Или я чего-то не понимаю? Как мне потом добратся до второй размерности?

anonymous(*)(2011-04-19 21:31:48)

[#] [Добавить метку] [Редактировать] Ответ на: Re: [C] Указатель на указатель на ... от anonymous 2011-04-19 21:10:01
avatar
Скрыть

Re: [C] Указатель на указатель на ...

Заменил все ** на * и получил те же ошибки:

  1.  >gcc test-2d-2.c
  2.  test-2d-2.c: В функции 'main'
  3.  test-2d-2.c:15: предупреждение: assignment from incompatible pointer type
  4.  test-2d-2.c:16: предупреждение: passing argument 1 of 'output' from incompatible pointer type

anonymous(*)(2011-04-19 21:34:10)

[#] [Добавить метку] [Редактировать] Ответ на: Re: [C] Указатель на указатель на ... от anonymous 2011-04-19 21:10:01
avatar
Скрыть

Re: [C] Указатель на указатель на ...

Тот же стандартный приём входных параметров для main выглядит также:

int main (int argc, char **argv)

anonymous(*)(2011-04-19 21:39:58)

[#] [Добавить метку] [Редактировать] Ответ на: [C] Указатель на указатель на ... от anonymous 2011-04-19 21:02:00
avatar
Скрыть

Re: [C] Указатель на указатель на ...

>void output (char **msg)
void output(char msg[][8]);

>for(n = 0; n < 1; n++)
for(n = 0; n < 2; n++)

P.S. у тебя однобайтная кодировка чтоли?

SystemV(*)(2011-04-19 22:01:54)

Emacs-w3m/1.4.414 w3m/0.5.3
[#] [Добавить метку] [Редактировать] Ответ на: Re: [C] Указатель на указатель на ... от SystemV 2011-04-19 22:01:54
avatar
Скрыть

Re: [C] Указатель на указатель на ...

А, ну и вообще не делай так. Объявляй str как *str[] = {...

SystemV(*)(2011-04-19 22:04:43)

Emacs-w3m/1.4.414 w3m/0.5.3
[#] [Добавить метку] [Редактировать] Ответ на: Re: [C] Указатель на указатель на ... от SystemV 2011-04-19 22:01:54
avatar
Скрыть

Re: [C] Указатель на указатель на ...

> у тебя однобайтная кодировка чтоли?
Я для микроконтроллера пишу, там вообще не строки, а массив байт. Вот что я примерно хочу:

c
uint8_t **global_ptr; // указатель на указатель на uint8_t
uint8_t a[][4] = {{...},{...},...}; // инициализирован реальными данными
uint8_t b[][4] = {{...},{...},...}; // другие данные; кол-во строк в a != b
// функция, куда я хочу передать указатель
void init (uint8_t **ptr)
{
        global_ptr = ptr;
}
...
int main (void)
{
        init(a);
        // что-то поделали с данными из массива a
        init(b);
        // теперь с b
}
 

В конце концов, такой пример с ** работает же:

c
#include
char **ptr;                  // тот самый указатель на указатель
int main (int argc, char **argv)
{
        ptr = argv;          // и даже присвоение работает
        if (argc > 1)
                printf("%s\n",ptr[1]);
        return 0;
}
 

anonymous(*)(2011-04-19 22:32:18)

[#] [Добавить метку] [Редактировать] Ответ на: Re: [C] Указатель на указатель на ... от SystemV 2011-04-19 22:04:43
avatar
Скрыть

Re: [C] Указатель на указатель на ...

> А, ну и вообще не делай так. Объявляй str как *str[] = {...
Мне нужен не массив указателей, а реально двумерный массив. Я потом буду поэлементно с содержимым работать.

anonymous(*)(2011-04-19 22:41:40)

[#] [Добавить метку] [Редактировать] Ответ на: [C] Указатель на указатель на ... от anonymous 2011-04-19 21:02:00
avatar
Скрыть

Re: [C] Указатель на указатель на ...

это же ФАКовский вопрос, чего учебников не читаешь?

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

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

bugmaker(*)(2011-04-20 05:29:33)

Opera/9.62 (X11; Linux i686; U; en) Presto/2.1.1
[#] [Добавить метку] [Редактировать] Ответ на: Re: [C] Указатель на указатель на ... от bugmaker 2011-04-20 05:29:33
avatar
Скрыть

Re: [C] Указатель на указатель на ...

> это же ФАКовский вопрос, чего учебников не читаешь?
Я искал на русском, но ничего внятного не нашёл.

Вот рабочий вариант (публикую прежде всего для себя):

c
#include stdio.h
#include stdint.h
const uint8_t string_super[][4] = {
        {'П', 'р', 'и', 'в'},
        {'е', 'т', ',', ' '}};
const uint8_t string_hyper[][4] = {
        {'л', 'о', 'р', 'э'},
        {'н', 'г', '!', '!'},
        {'!', '!', '!', '\n'}};
const uint8_t (*string_global)[4];      // указатель на массив
uint8_t string_global_lenght=0;
void init (const uint8_t (*msg)[4], uint8_t len)
{
        string_global=msg;
        string_global_lenght=len;
}
void output (void)
{
        uint8_t n,m;
        for(n = 0; n < string_global_lenght; n++)
                for(m = 0; m < 4; m++)
                        printf("%c",string_global[n][m]);
}
int main (void)
{
        init(string_super,2);
        output();
        init(string_hyper,3);
        output();
        return 0;
}
 

Компилируется без ошибок и предупреждений, выводит

  1.  >./a.out
  2.  Привет, лорэнг!!!!!

anonymous(*)(2011-04-20 12:00:27)

[#] [Добавить метку] [Редактировать] Ответ на: Re: [C] Указатель на указатель на ... от anonymous 2011-04-20 12:00:27
avatar
Скрыть

Re: [C] Указатель на указатель на ...

зойчем тебе на русском? Там всё просто. В сях нету многомерных массивов, совсем. Ты передаёшь одномерный массив, в котором каждый элемент является одномерным массивом. При адресации элемента например a[1][1] к указателю на первый элемент массива a[0][0] прибавляется смещение, то есть вычисляется сначала первый элемент "внутреннего" массива, и это смещение зависит от его ширины w: a+w*1+1. Поэтому либо ширина "внутреннего" массива должна быть задана на момент компиляции, либо просто передаёшь в функцию указатель на первый элемент, ширину массива, а в функции вместо оператора массива используешь явную арифметику указателей, то есть вместо a[1][1] так и пишешь, *(a+w*1+1).

bugmaker(*)(2011-04-21 16:43:55)

Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.14) Gecko/20101013 Ubuntu/9.04 (jaunty) Shiretoko/3.5.14
Этот тред читают 1 пользователь:
Анонимных: 1
Зарегистрированных: 0




(c) 2010-2020 LOR-NG Developers Group
Powered by TimeMachine

Valid HTML 4.01 Transitional Правильный CSS!