Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Ошибка при обращении к матрице через указатель 
V
    Опции темы
Genady
Дата 28.1.2012, 13:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 70
Регистрация: 25.6.2009

Репутация: нет
Всего: нет



 Здравствуйте форумчане!
Нужен совет - как избежать ошибки сбоя программы  - Segmentation fault,   при работе с указателем на квадратную матрицу.
 В ниже приведённом примере я использую классический способ индексации матрицы через [i][j] .
  За ранее благодарен.
Гена.


Код

 #include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include<stdbool.h>
 #include <ctype.h>

 #define SIZE 15
 
 typedef int matrix[SIZE][SIZE];
  
 void main(void) {

   matrix MAT_A;
   matrix *the_mat;
   int i,j,num;
   
   the_mat = &MAT_A;
  
  for(i = 0; i <  SIZE; i++)
       for(j = 0; j <  SIZE; j++){
         printf(" Enter the data for MAT_A[%d][%d] member \n", i, j );
         scanf("%d", &num);
         *the_mat[i][j] = num;
  
  }//end of for
  printf("\n\n\n");   

  for(i = 0; i <  SIZE; i++)
       for(j = 0; j <  SIZE; j++){
          if(j%SIZE != 0) 
             printf("%d \t", *the_mat[i][j]);
          else{ 
              printf("\n");
              printf("%d \t", *the_mat[i][j]);  
           }
   }//end of for
   printf("\n\n\n");

 }//end of main
  


Это сообщение отредактировал(а) Genady - 28.1.2012, 13:47
PM MAIL   Вверх
bsa
Дата 28.1.2012, 14:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



ошибки можно избежать если изучить приоритеты операций. Операция * имеет более низкий приоритет, нежели []. Тебе нужно писать так: (*the_mat)[i][j]

Добавлено через 50 секунд
кстати, функция main должна возвращать int, а не void. Видимо, ты используешь старый компилятор - современные это считают ошибкой.
PM   Вверх
Genady
Дата 28.1.2012, 18:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 70
Регистрация: 25.6.2009

Репутация: нет
Всего: нет



Спасибо bsa!
Я учёл ваши примечания, но всё равно ошибки сбоя программы  - Segmentation fault - избежать не удаётся.

Хотя надо отметить что уже  выводятся на экран содержимое ячеек матрицы, значит иду в правильном направлении
  при запуске программы:

Код

 #include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include<stdbool.h>
 #include <ctype.h>

 #define SIZE 4
 
 typedef int matrix[SIZE][SIZE];
  
 int main() {

   matrix MAT_A;
   matrix *the_mat;
   int i,j,num;
   
   the_mat = &MAT_A;
  
  for(i = 0; i <  SIZE; i++)
       for(j = 0; j <  SIZE; j++){
         printf(" Enter the data the MAT_A[%d][%d] member \n", i, j );
         scanf("%d", &num);
         (*the_mat)[i][j] = num;
  }//end of for
  printf("\n\n\n");   

  for(i = 0; i <  SIZE; i++)
       for(j = 0; j <  SIZE; j++){
          if(j%SIZE != 0) 
             printf("%d \t", *the_mat[i][j]);
          else{ 
              printf("\n");
              printf("%d \t", *the_mat[i][j]);  
           }
   }//end of for
   printf("\n\n\n");
 return 0;
 }//end of main
  


 при вводе 16_ти целых положительных чисел  от 1_го до 16_т,  output  таков:

 

1    5    9    13    
14    1307461    134514192    1    
-1077112880    1    -1217356992    -1077112856    
0    0    1    134513828 

 Может быть надо исходить из концепции - что в программе я использую указатель the_mat  на сложную переменую MAT_A, типа  matrix, которая  определена определением: typedef int matrix[SIZE][SIZE]  как матрица целых чисел. И надо таки да  думать о динамическом бронировании памяти под  матрицы с помощью malloc и последующего освобождения памяти с помощью free ? -  Я не знаю, т.к. с проблемами указателей памяти присущеми в С/С++ - я до сих пор серьёзно не сталкивался, хотя и наслышан о них и которые отравили жизнь немало талантливым программистам, наверное недаром и не от хорошей жизни таким корифеям С/C++ как James Gosling, Mike Sheridan, и  Patrick Naughton  - пришлось разработать Java, в концепцию которой вошли и полный отказ от прямой адресации памяти, там роль указателей выполняют классы и те же матрицы. 
 Но надо отдать должное С/C++ т.к без них не было того что теперь называется Java. Программисты такого уровня ковались и куются в недрах С/С++.
Но вернёмся к наболевшему:
В приведённом мной коде - операция присвоения:   the_mat = &MAT_Ab
 Т.е. здесь - как я понимаю - указатель   the_mat после операции присвоения будет содержать - адрес первой ячейки матрицы MAT_A:  MAT_A[0][0],  что даёт возможность индексации ячеек матрицы для операции присвоения или показа содержимого ячейки матрицы с помощью комманды    *the_mat[i][j] или *(*(the_mat + i) + j)).
   Но судя по input : - 10_ти значные цифры это -  явно адреса каких то переменных хранимых в ячейках - которые ни в коем случае нельзя трогать  - здесь имеет место ошибка при адресации, т.е. указатель обращается ("ходит на лево") за пределы забронированного с помощью int matrix[SIZE][SIZE]  участка памяти для матрицы MAT_A.
    Сама идея перемещения указателя по матрице с помощью комманды the_mat + i (так что бы i<=SIZE) или the_mat ++ в цикле while(the_mat) - основанна на утверждении что участок бронируемый под память для массива(матрицы) - сплошной, так что бы ячейки матрицы последовательно следовали друг за другом, причём под каждую ячейку забронировано равное количество байтов , которое зависит от типа данных которое определено при объявлении типа данных 




Это сообщение отредактировал(а) Genady - 28.1.2012, 18:27
PM MAIL   Вверх
bsa
Дата 28.1.2012, 18:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Genady, ты про строки 31 и 34 забыл. Там тоже скобки надо расставить.

Добавлено через 4 минуты и 24 секунды
Цитата(Genady @  28.1.2012,  19:21 Найти цитируемый пост)
В приведённом мной коде - операция присвоения:   the_mat = &MAT_Ab
 Т.е. здесь - как я понимаю - указатель   the_mat после операции присвоения будет содержать - адрес первой ячейки матрицы MAT_A:  MAT_A[0][0],  что даёт возможность индексации ячеек матрицы для операции присвоения или показа содержимого ячейки матрицы с помощью комманды    *the_mat[i][j] или *(*(the_mat + i) + j)).

А по моему, the_mat - это указатель на массив. Да, это указатель на первую ячейку... но трехмерной матрицы!!! Т.е. первый индекс задает номер матрицы, второй задает номер строки, а третий - номер столбца. Так как у тебя не массив матриц, то первый индекс должен быть всегда 0.
PM   Вверх
Genady
Дата 29.1.2012, 04:31 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 70
Регистрация: 25.6.2009

Репутация: нет
Всего: нет



Ещё раз спасибо - bsa!
Да - вы правы! -  как вы сказали - " the_mat - это указатель на массив. Да, это указатель на первую ячейку... но трехмерной матрицы!!! ".
      Ваше мнение подкрепило мои выводы.
Т.к. мне не нужно работать с трёхмерной матрицей, то я ввёл незначительные изменения в предыдущий код:
Код

 #include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include<stdbool.h>
 #include <ctype.h>

 #define SIZE 4
 
 typedef int matrix[SIZE][SIZE];
  
 int main() {

   matrix MAT_A;
   int *the_mat;
   int i,j,num;
   
   the_mat = &MAT_A[0][0];
  
  for(i = 0; i <  SIZE; i++)
       for(j = 0; j <  SIZE; j++){
         printf(" Enter the data the MAT_A[%d][%d] member \n", i, j );
         scanf("%d", &num);
         ((the_mat+i)[j]) = num;// also  *((the_mat + i) + j)

  }//end of for
  printf("\n\n\n");   

  for(i = 0; i <  SIZE; i++)
       for(j = 0; j <  SIZE; j++){
          if(j%SIZE != 0) 
             printf("%d \t",   ((the_mat+i)[j]));//*((the_mat + i) + j));   
          else{ 
              printf("\n");
              printf("%d \t",  ((the_mat+i)[j]));    // well   *((the_mat + i) + j));
      }//end of internal for
   }//end of external for
   printf("\n\n\n");
  return 0;
 }//end of main
  

   При чём для работы с матрицей содержащей целые числа - я объявил указатель на целые числа  
Код
  int *the_mat; 

  и присвоил ей адрес первой ячейки матрицы MAT_A 
Код
the_mat = &MAT_A[0][0];

. 
 То -что я сделал в предыдущей версии кода - делать недопустимо!!! - Я пытался работать с указателем на матрицу, типа 

matrix которая при перемещении - перемещается "Семи-мильными шагами ", проскакивая за раз весь массив отсюда и была ошибка в сегментации.
  Что касается (*the_mat)[i][j] создания приоритета для унарного оператора *   -  в заключении его в круглые скобки, то здесь компайлер упорно выдавал сообщения о невозможности операции присваивания - вследствии несоответствия операндов  по типу данных -т.е требовал выполнения кастинга (замещения).
В общем удалось обойти проблему так: 
Код
 ((the_mat+i)[j]) = num;

 или так 
Код

  *((the_mat + i) + j) =  num;

PM MAIL   Вверх
xvr
Дата 29.1.2012, 12:10 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Срочно читать букварь по указателям и массивам в С (и не здесь - к Linux это не имеет никакого отношения)

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.3602 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.