Порядок объявления переменных (если быть точным, то массивов) (в программе очень даже имеет значение! Недоумеваю. Почему?)

Модератор: Модераторы разделов

promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Порядок объявления переменных (если быть точным, то массивов)

Сообщение promov »

Друзья! Вот текст моей программы

Код: Выделить всё

#include <stdio.h>
     #include "247.c"
     int main () {
      int sdvig (int b [5], int c [47]);

      int b [5]= {81, 53, 82, 123, 133};
      int f [5]= {82, 123, 133};
      int c [47];


      printf ("f [0]= %d        f [0]= %d        f [0]= %d\n", f [0], f [1], f [2]);
      sdvig (b, c);
      printf ("f [0]= %d        f [0]= %d        f [0]= %d\n", f [0], f [1], f [2]);

      return 0;
     }


Вот функция sdvig (b, c) это моя рабочая, так сказать функция, она определена у меня в файле 247.c, который я подключил. Работает без нареканий. Но! Упорно меняет значение элемента f [0], который не имеет к ней никакого отношения! Я не зря показал вам, что вызываю функцию printf. После первого вызова printf () на экране- значения f [0], f [1] и f [2]. Всё как положено. 82, 123 и 133 соответственно. А после вызова функции sdvig (b, c) значение f [0] становится равным 21. Что это? Это как-то даже нехорошо!
...Помогает, что очень странно, вот это. Вот меняем местами определения массивов f и c

Код: Выделить всё

int c [47];
int f [5]= {82, 123, 133};


Теперь всё в порядке. Значение элемента f [0] как было 82 до вызова sdvig (b, c), так им и остаётся. Всё это очень-очень странно, друзья! Не разъясните ли вы мне ситуацию? Ваш promov
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
Аватара пользователя
KiWi
Бывший модератор
Сообщения: 2521
Статус: статус, статус, статус

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение KiWi »

Все конечно же должны сами догадаться, что в этом sdvig'е происходит?
Кратко -- затираете память f, когда работаете с одним из массивов/доп. переменной/тп...
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение promov »

Затираю... Затираю, да... Неужели это возможно в принципе? На всех углах (читай во всех книгах) только и говорят о том, как это круто, что в языке C можно делать объявления переменных в каком захочешь месте. Даже в скобках после "for", когда заходишь в какой-нибудь цикл, можно объявить переменную-счётчик. А тут надо же, в самом начале, ещё до собственно выполнения программы переставил объявления местами и на тебе- попал пальцем в небо.

...А что касается функции sdvig (), то я не без умысла не стал писать лишние подробности. Не всё ли равно, что она делает? Важны аргументы- массив f в их число не входит, а, значит, меняться не должен.
Вот так, друзья, я идумал до недавнего времени. А теперь обескуражен. Какие ещё неоговорённые подвохи ждут меня на пути, кабы знать...
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
Аватара пользователя
dey
Сообщения: 335
ОС: OpenSuse 11.1

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение dey »

promov писал(а):
18.03.2008 21:08
Затираю... Затираю, да... Неужели это возможно в принципе? На всех углах (читай во всех книгах) только и говорят о том, как это круто, что в языке C можно делать объявления переменных в каком захочешь месте. Даже в скобках после "for", когда заходишь в какой-нибудь цикл, можно объявить переменную-счётчик. А тут надо же, в самом начале, ещё до собственно выполнения программы переставил объявления местами и на тебе- попал пальцем в небо.

Значение элемента в объявленном массиве не может зависеть от дальнейшего порядка следования операторов/вызовов функций и тд. если в них нет обращения к этому массиву. И не зависит о места объявления, в данном случае точно
Все таки стоит привести код ф-ии sdvig()
В сознательных действиях должен присутствовать существенный неалгоритмический компонент.
Roger Penrose,The Emperor's New Mind
Спасибо сказали:
Аватара пользователя
uptime
Сообщения: 1661
Статус: Drinker with computing problems
ОС: kubuntu 8.04

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение uptime »

promov писал(а):
18.03.2008 21:08
Затираю... Затираю, да... Неужели это возможно в принципе? ...
...
...А что касается функции sdvig (), то я не без умысла не стал писать лишние подробности. Не всё ли равно, что она делает? Важны аргументы- массив f в их число не входит, а, значит, меняться не должен.
...

Си позволяет писать за границы массива, и этого оказывается вполне достаточно, чтобы перетереть что угодно в программе. Не удивлюсь, если в новом варианте, проинициализировав массив c[], вы обнаружите, что теперь портится его содержимое.

успехов
The answer, my friend, is blowin' in the wind.
The answer is blowin' in the wind.
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение promov »

dey писал(а):
18.03.2008 21:58
Значение элемента в объявленном массиве не может зависеть от дальнейшего порядка следования операторов/вызовов функций и тд. если в них нет обращения к этому массиву. И не зависит о места объявления, в данном случае точно
Все таки стоит привести код ф-ии sdvig()
Ваши бы слова да Богу в уши... Имеем:

1) Отсортированный массив "a" элементов типа int в количестве 52. Первый элемент равен 81, последний 132, разница между соседними элементами 1

2) Неотсортированный массив "b" элементов типа int в количестве 5, неповторяющихся. Каждый элемент в диапазоне от 81 одного до 132 включительно.

Задача: убрать из массива "a" все элементы массива "b", создав, таким образом третий массив "c" из 47 элементов (52- 5= 47). Вот этим и занимается функция sdvig. Вот её текст с необходимыми пояснениями

Код: Выделить всё

//Функция принимает 2 аргумент- два массива. Заполненный "b" и незаполненный "c", который и заполняет
void sdvig (int b [5], int c [47]) {

   //Это будет копия массива b. Суть: отсортировываем копию и с ней работаем. А сам массив b сортировать нельзя по некоторым причинам.
   int b1 [5];

   //A вот из этого массива "a" мы и "вычленяем" маленький массив "b"
   int a [52]= {81, 82, 83, 84, 85,
                86, 87, 88, 89, 90,
                91, 92, 93, 94, 95,
                96, 97, 98, 99, 100,
                101, 102, 103, 104, 105,
                106, 107, 108, 109, 110,
                111, 112, 113, 114, 115,
                116, 117, 118, 119, 120,
                121, 122, 123, 124, 125,
                126, 127, 128, 129, 130,
                131, 132};
   char ia= 0;// Cчётчик элементов массива a
   char ib1= 0;// Cчётчик элементов массива b1
   char ic= 0;// Cчётчик элементов массива c

   //Это вспомогательные штуки
   int i, j, k;

   //Прежде всего сделаем копию массива b. Массив b1
   for (i= 0; i< 5; ++ i ) {
    b1 [i]= b [i];
   }

   //Теперь эту копию отсортируем.
   for (i= 0; i< 4; i++) {
    for (j= i+ 1; j<  5; j++) {
     if (b1 [i]> b1 [j]) {
      k= b1 [i];
      b1 [i]= b1 [j];
      b1 [j]= k;
     }
    }
   }

   //А это собственно "вычленение". Ничего сложного, как видим. Внешний цикл перебирает элементы массивов a и c. И при просмотре каждого элемента массива "a" просто сравнивает его с элесментом массива b1. Если не равны- просто копирует элемент массива a в элемент массива c. Если равны- счётчик элементов массива c увеличивается на 1, чтобы больше этот элемент не рассматривался. А счётчик элементов массива c просто уменьшается на 1. (В это случае по заходу во внешний цикл он потом увеличится и станет таким, каким и был.)
   for (ia, ic; ia< 52; ++ ia, ++ ic) {
    if (!(a [ia]== b1 [ib1])) {
     c [ic]= a [ia];
    }
    else {
     ib1++;
     ic--;
    }
   }
}

  //Ну это понятно для чего. Для проверки работоспособности функции просто расскоментируем ниженаписанное и компилируем программу обычным способом.
  /*
  #include <stdio.h>
  int main () {
   return 0;
  }
 */


А это вот текст программы, которая использует эту функцию. Она объявлена, напомню (у меня) в файле 247.c

Код: Выделить всё

 #include <stdio.h>
  #include "247.c"
       int main () {
        void sdvig (int b [5], int c [47]);

        int b [5]= {81, 120, 131, 132, 92};
        int f [5]= {82, 123, 133};
        int c [47];


        printf ("f [0]= %d        f [1]= %d        f [2]= %d\n", f [0], f [1], f [2]);
        sdvig (b, c);
        printf ("f [0]= %d        f [1]= %d        f [2]= %d\n", f [0], f [1], f [2]);

        return 0;
       }

А это вывод

Код: Выделить всё

 f [0]= 82        f [1]= 123        f [2]= 133
   f [0]= 22        f [1]= 21        f [2]= 133


Вот почему f [0] и f [1] изменено? И я не знаю... А если в тексте последней программы объявления массивов f и c поменять местами, тогда f [0] и f [1] не изменяются...

uptime писал(а):
18.03.2008 22:14
[Си позволяет писать за границы массива, и этого оказывается вполне достаточно, чтобы перетереть что угодно в программе. Не удивлюсь, если в новом варианте, проинициализировав массив c[], вы обнаружите, что теперь портится его содержимое.

успехов
Я прямо не знаю, что и делать...
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
Аватара пользователя
uptime
Сообщения: 1661
Статус: Drinker with computing problems
ОС: kubuntu 8.04

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение uptime »

алгоритм достаточно путаный, без бутылки не разобраццо. Однако массив c[47], а счетчик ic ограничен значением 52. Видимо проблемы здесь.

успехов
The answer, my friend, is blowin' in the wind.
The answer is blowin' in the wind.
Спасибо сказали:
Аватара пользователя
KiWi
Бывший модератор
Сообщения: 2521
Статус: статус, статус, статус

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение KiWi »

try c[52]
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение promov »

Да нет, счётчик ic не ограничен значением 52. Этим значением ограничен счётчик ia. Посколько в ia 52 элемента, он все 52 и должен рассмореть. И только 47 из них скопируются. Если наодятся равные элементы, просто копирования не происходит.

А алгоритм прост достаточно. Если прочитано условие и цель, тогда без труда понятно, что... Ну просто делается копия маленького массива (из 5-ти элементов) и эта копия сортируется и вычленяется. Само это вычленение в 9-ти несчастных строчках, 3 из которых- фигурные скобки.
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
Аватара пользователя
ZyX
Сообщения: 355
ОС: Gentoo

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение ZyX »

1) Где ограничение в 47 на переменную ic? Она же вместе с ia изменяется, но на ia ограничение есть. Не зря тут про выход за пределы говорили. 52-3=49, 49-47=2 - вышли за пределы массива как раз на размер двух переменных.
2) При передаче массива c в качестве параметра создается локальная копия оного, а потому массив c в main не изменяется. Я так частенько аргументы в качестве счетчиков использую. Передавать надо указатель, но здесь, вообще-то, лучше массив в виде указателя возвращать. И указатель на какую-нибудь int в качестве аргумента для того, чтобы можно было узнать длину возвращенного массива.

Я, впрочем, вообще взял за правило для массивов использовать только указатели - при желании всегда можно сделать realloc для изменения размеров.

3) А зачем #include "*.c". Вместо этого есть объявление функций как extern и компиляция нескольких файлов сразу или по очереди в *.o с последующей линковкой (gcc -o somefile.o -c somefile.c ; gcc -o somefile2.o -c somefile2.c ; ... ; gcc -o projectname *.o).
4) Зачем есть массив a, если он легко реализуется функцией a(int index){return (81+index);}? Или это часть задания?
5) А вы сами учитесь, или у вас такой учитель, что них*я не объясняет? В первом случае незнание таких вещей еще простительно, но не во втором.

Ой, уже частично успели ответить

Вообще, отлично подойдет динамическое выделение памяти под c по мере надобности: при отсутствии совпадений в c записывается значение, длина увеличивается на 1 - она получается всегда на sizeof(int) больше, чем надо. Или наоборот - сначала выделение, потом приравнивание. Кроме того, из-за создания локальных копий любой пременной, данной в качестве аргумента, можно не создавать копию b - в main при сортировке b не изменится, если, конечно же, не передавать указатель.
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение promov »

KiWi писал(а):
19.03.2008 00:11
try c[52]
Не понял. Честно. Это моя ошибка? Но уменя нигде не написано c [52]... Должно быть c [52]?
Функция sdvig по условию принимает массив из 47 элементов и запонлняет его. Всё. Мне нет надо 52, мне надо 47. Извините.

ZyX писал(а):
19.03.2008 00:19
5) А вы сами учитесь, или у вас такой учитель, что них\%u0443я не объясняет? В первом случае незнание таких вещей еще простительно, но не во втором.
Сам. От и до. Сейчас разбираться буду. Спасибо, что откликнулись.
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
Аватара пользователя
ZyX
Сообщения: 355
ОС: Gentoo

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение ZyX »

Интересно - при быстром ответе %u0443 заменился на символ у. Не катит, однако, такое против модераторов
Спасибо сказали:
Аватара пользователя
KiWi
Бывший модератор
Сообщения: 2521
Статус: статус, статус, статус

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение KiWi »

promov писал(а):
19.03.2008 00:26
Функция sdvig по условию принимает массив из 47 элементов и запонлняет его. Всё. Мне нет надо 52, мне надо 47. Извините.

Повторю предыдущие посты

Код: Выделить всё

  for (ia, ic; ia< 52; ++ ia, ++ ic) {

-- не накладывает никаких ограничений на ic.
В данном конкретном случае -- этим ограничением будет 52(при произвольных массивах).

Если так уж не хочется делать c[52], то тогда for стоит сделать:

Код: Выделить всё

for(ia = 0, ic = 0; ia < 52 && ic < 47 && ib1 < 5; ++ia, ++ic)


А вообще весь for можно и переписать(если нигде не накосячил) для c[47]:

Код: Выделить всё

for (ia = 0, ic = 0; ia < 52 && ic < 47 && ib1 < 5; ++ia) {
if (a[ia] != b1[ib1]) {
c[ic++] = a[ia];
} else {
++ib1;
}
}
Спасибо сказали:
Аватара пользователя
ZyX
Сообщения: 355
ОС: Gentoo

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение ZyX »

Кстати, насчет моего 3) пункта: до того, как я спросил нашего учителя по ЭВМ, а что вообще в #include пишут, у меня в заголовочном файле были такие же функции, и, кроме того, я не понимал, что файл #include препроцессор просто вставляет вместо этой директивы.

Кстати, а здесь опечатка:

Код: Выделить всё

for (ia = 0, ic = 0;
     ia < 52 && ic < 47 && ib1 < 5;
     ++ia)
{
    if (a[ia] != b1[ib1])
        c[ic++] = a[ia];
    else
        ++b1; /* У нас, все-таки, не указатель,
               * здесь ib1 должно стоять
               */
}
(лишние скобки поубирал, переделал форматирование)

Кстати, если надо, могу показать, как то же с указателями сделать вместо массивов. И с realloc для c.
Спасибо сказали:
Аватара пользователя
wzrd
Сообщения: 323
ОС: Debian Lenny

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение wzrd »

Код:

//Функция принимает 2 аргумент- два массива. Заполненный "b" и незаполненный "c", который и заполняет int sdvig (int b [5], int c [47]) { //Это будет копия массива b. Суть: отсортировываем копию и с ней работаем. А сам массив b сортировать нельзя по некоторым причинам. int b1 [5]; //A вот из этого массива "a" мы и "вычленяем" маленький массив "b" int a [52]= {81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132}; char ia= 0;// Cчётчик элементов массива a char ib1= 0;// Cчётчик элементов массива b1 char ic= 0;// Cчётчик элементов массива c //Это вспомогательные штуки int i, j, k; //Прежде всего сделаем копию массива b. Массив b1 for (i= 0; i< 5; ++ i ) { b1 [i]= b [i]; } //Теперь эту копию отсортируем. for (i= 0; i< 4; i++) { for (j= i+ 1; j< 5; j++) { if (b1 [i]> b1 [j]) { k= b1 [i]; b1 [i]= b1 [j]; b1 [j]= k; } } } //А это собственно "вычленение". Ничего сложного, как видим. Внешний цикл перебирает элементы массивов a и c. И при просмотре каждого элемента массива "a" просто сравнивает его с элесментом массива b1. Если не равны- просто копирует элемент массива a в элемент массива c. Если равны- счётчик элементов массива c увеличивается на 1, чтобы больше этот элемент не рассматривался. А счётчик элементов массива c просто уменьшается на 1. (В это случае по заходу во внешний цикл он потом увеличится и станет таким, каким и был.) for (ia, ic; ia< 52; ++ ia, ++ ic) { if (!(a [ia]== b1 [ib1])) { c [ic]= a [ia]; } else { ib1++; ic--; } } return 0; } #include <stdio.h> // #include "247.c" int main () { // void sdvig (int b [5], int c [47]); int b [5]= {81, 120, 131, 132, 92}; int f [5]= {82, 123, 133}; int c [47]; printf ("f [0]= %d f [1]= %d f [2]= %d\n", f [0], f [1], f [2]); sdvig (b, c); printf ("f [0]= %d f [1]= %d f [2]= %d\n", f [0], f [1], f [2]); return 0; }

Код: Выделить всё

$ gcc unit.c
$ ./a.out
f [0]= 82        f [1]= 123        f [2]= 133
f [0]= 82        f [1]= 123        f [2]= 133

код не менял, только объединил все в один файл и закомментировал одну строчку.
Спасибо сказали:
Аватара пользователя
uptime
Сообщения: 1661
Статус: Drinker with computing problems
ОС: kubuntu 8.04

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение uptime »

Код: Выделить всё

 #include <stdio.h>
 #include "247.c"
      int main () {
       void sdvig (int b [5], int c [47]);
...

promov, а у вас компилятор на это не ругался? Сначала функция была объявлена как возвращающая целое значение, а потом переопределена как ничего не возвращающая. Возможно проблемы с этим и связаны..
в варианте, предложенном wzrd, этой ошибки нет.
The answer, my friend, is blowin' in the wind.
The answer is blowin' in the wind.
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение promov »

uptime писал(а):
19.03.2008 13:31

Код: Выделить всё

 #include <stdio.h>
    #include "247.c"
         int main () {
          void sdvig (int b [5], int c [47]);
   ...

promov, а у вас компилятор на это не ругался? Сначала функция была объявлена как возвращающая целое значение, а потом переопределена как ничего не возвращающая. Возможно проблемы с этим и связаны..
Нет, тут всё нормально.
Сперва действительно функеция sdvig () возвращала у меня значение типа int (cм. сообщение N 1). А по запросу текста этой функции (сообщение N 4) я её проанализировал и сделал вывод, что она зря что-то там возвращает. И исправил. Теперь она стала не "int sdvig", а "void sdvig". И в том и в другом случае всё компилировалось без ругани, изменялся массив f, что нехорошо.
...Сейчас, друзья, я прнишёл с работы и буду со всем остальным разбираться.
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение promov »

wzrd писал(а):
19.03.2008 09:26
// #include "247.c"
// void sdvig (int b [5], int c [47]);
код не менял, только объединил все в один файл и закомментировал одну строчку.
...Две строчки, если уж на то пошло.
wzrd иZyX! Вы поймите, тут очень важно не просто решить, а разобраться, где в моём варианте ошибка.
ZyX, (сообщение N , пункты 2-4). Я не сомневаюсь, что следуя вашим советам, я задачу решу. Но, 1) с указателями на данный момент я знаком лишь очень поверхностно 2) пункты 3 и 4... это тоже... не готов я к ним пока. Но не спешите меня ругать. Задачу нужно решить исходя из того, что я знаю. Хорошо, не решить. Но объяснить, почему она не имеет решения. А среди прочего я знаю: в каком порядке хочешь, в таком переменные и объявляй. Если в функцию передаётся массив, то в неё передаётся указатель на первый элемент этого массива, а никакого другого. И с этим массивом она и работает. И, работая с массивом "c" она выходит за его границы (47 элементов), т. к. на счётчик ic элементов этоого массива ограничений не установлено. Сейчас подробнее напишу. Не торопитесь отвечать.
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
Аватара пользователя
wzrd
Сообщения: 323
ОС: Debian Lenny

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение wzrd »

promov писал(а):
19.03.2008 21:16
wzrd писал(а):
19.03.2008 09:26
// #include "247.c"
// void sdvig (int b [5], int c [47]);
код не менял, только объединил все в один файл и закомментировал одну строчку.
...Две строчки, если уж на то пошло.
wzrd иZyX! Вы поймите, тут очень важно не просто решить, а разобраться, где в моём варианте ошибка.

инклуд я изменил из-за того что он там не нужен, а прототип я убрал из-за того что компилятор ругался и вообще я не вижу смысла в нем. а чтобы решить эту задачу нужно пробывать всё, чтобы знать в какую сторону копать. кстати попробуйте написать это всё в одном файле.
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение promov »

wzrd писал(а):
19.03.2008 21:29
инклуд я изменил из-за того что он там не нужен, а прототип я убрал из-за того что компилятор ругался и вообще я не вижу смысла в нем. а чтобы решить эту задачу нужно пробывать всё, чтобы знать в какую сторону копать. кстати попробуйте написать это всё в одном файле.
Ну, понятное дело, что ругался, Просто я глупость сделал. Написал функцию sdvig так:

int sdvig (<список аргументов>) Х
return 0;
}

А в прототипе было написано
void sdvig

Сейчас я всё исправил там. Теперь она везде "void". И ещё: мне мою функцию sdvig в моём проекте придётся несколько (много) раз вызывать из разных мест программы. Так что хочешь-не хочешь, а придётся её оформлять отдельным исполняемым файлом, чтобы его в нужное время подключать.
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
Аватара пользователя
wzrd
Сообщения: 323
ОС: Debian Lenny

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение wzrd »

promov писал(а):
19.03.2008 21:40
Сейчас я всё исправил там. Теперь она везде "void". И ещё: мне мою функцию sdvig в моём проекте придётся несколько (много) раз вызывать из разных мест программы. Так что хочешь-не хочешь, а придётся её оформлять отдельным исполняемым файлом, чтобы его в нужное время подключать.

ну я же не говорю что не надо подключать просто попробуйте.
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение promov »

Ничего не поделать. Хотел я без указателей-массивов обойтись, видать, не получится. Сейчас буду разбираться с указателями-массивами. Потом про ic будет разговор.
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
Аватара пользователя
ZyX
Сообщения: 355
ОС: Gentoo

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение ZyX »

promov писал(а):
19.03.2008 21:16
Если в функцию передаётся массив, то в неё передаётся указатель на первый элемент этого массива, а никакого другого.
Однако, передается не указатель, а содержимое массива. Указатель необходимо передавать явно как указатель, иначе создастся копия. Впрочем, я об этом писал.
Поэтому, дабы не путаться с указателями, лучше этот c сделать возвращаемым значением. А то у меня в одной функции один раз аж char *** в аргументах появился. Впрочем, она и без него так и не заработала в этой части (должна была открывать последовательно файлы, представленные в виде списка char *, через запятую. Имена файлов отправлялись в этот указатель. Файлы открывала, но в эту переменную их имена так и не удалось записать как следует. А учитель наш, как назло, заболел.)

Ничего не поделать. Хотел я без указателей-массивов обойтись, видать, не получится. Сейчас буду разбираться с указателями-массивами. Потом про ic будет разговор.
Получится, но указатели - вещь весьма важная, так что чем раньше освоите, тем проще будет.
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение promov »

ZyX писал(а):
19.03.2008 22:27
promov писал(а):
19.03.2008 21:16
Если в функцию передаётся массив, то в неё передаётся указатель на первый элемент этого массива, а никакого другого.
Однако, передается не указатель, а содержимое массива.
Нет уж, позвольте!

"Но когда передаётся весь массив, то содержимое оригинального массива не копируется в формальный параметр типа массив. Вместо этого в фунцию передаётся информация о местонахождении в памяти элементов массива. Поэтому все изменения, сделанные для формального параметра типа массив, на самом делде изменяют значения элементов оригинального массива, а не его копии, которой просто нет" (Стефан Кочан, "Программирование на языке C", Москва- Санкт- Петербург, Киев, 2007 г.)

"Если в функцию передаётся имя массива, по сути туда поступает адрес первого элемента" (K&R)

Наконец, такие соображения: при объявлении функции, если она принимает аргумент-массив, его размер писать необязательно? Почему? Разве не нужно в функции создать место для этого массива? Получается, не нужно- она работает с одним массивом (cуть с одним и тем же массивом), а не с его копией, как уже было сказано.

...А по моему вопросу- я, кажется, начал понимать в чём дело. У меня массив "c" состоит из 46-ти элементов. В процессе выполнения функции счётчик элементов принимает значение 47. И имеет место быть выражение "c [ic]". Идёт то есть обращение к 47-му элементу, которого просто нет. Поэтому всё и нарушается к чёртовой матери. Что-то такое.
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
Аватара пользователя
uptime
Сообщения: 1661
Статус: Drinker with computing problems
ОС: kubuntu 8.04

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение uptime »

promov писал(а):
19.03.2008 22:51
...А по моему вопросу- я, кажется, начал понимать в чём дело. У меня массив "c" состоит из 46-ти элементов.

Как это? он везде объявлялся как int c[47];
The answer, my friend, is blowin' in the wind.
The answer is blowin' in the wind.
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение promov »

uptime писал(а):
19.03.2008 23:22
promov писал(а):
19.03.2008 22:51
...А по моему вопросу- я, кажется, начал понимать в чём дело. У меня массив "c" состоит из 46-ти элементов.

Как это? он везде объявлялся как int c[47];
Тьфу. Извините. Конечно, из 47-ми. Я исправил всё. Точно, нельзя допускать "c [ic]" при ic> 46. Сейчас всё работает. Всем спасибо. Впереди тык скыть новая темка.
P. S. Вообще, то, о чём говорилось в этой теме для меня впервые. Сам бы я не дошёл. Спасибо всем.
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
Аватара пользователя
ZyX
Сообщения: 355
ОС: Gentoo

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение ZyX »

promov писал(а):
19.03.2008 22:51
"Если в функцию передаётся имя массива, по сути туда поступает адрес первого элемента" (K&R)
Извиняюсь, был неправ. Но переменных простых это касается, а массивы я не использую, потому и ошибся. Надо все-таки прочитать K&R, буду меньше глупостей говорить.

Наконец, такие соображения: при объявлении функции, если она принимает аргумент-массив, его размер писать необязательно? Почему? Разве не нужно в функции создать место для этого массива? Получается, не нужно- она работает с одним массивом (cуть с одним и тем же массивом), а не с его копией, как уже было сказано.
А об этом я мог бы и без K&R подумать. Так что учится мне еще.
Спасибо сказали:
Аватара пользователя
wzrd
Сообщения: 323
ОС: Debian Lenny

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение wzrd »

Всё таки интересно почему у меня работает...
Спасибо сказали:
Аватара пользователя
dey
Сообщения: 335
ОС: OpenSuse 11.1

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение dey »

У меня тоже все нормально работает
В сознательных действиях должен присутствовать существенный неалгоритмический компонент.
Roger Penrose,The Emperor's New Mind
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Порядок объявления переменных (если быть точным, то массивов)

Сообщение promov »

Не знаю, что у вас там работает, остаётся только догадываться. Причину того, что нечто у вас работает нормально, я вижу в пространственной тык скыть организации памяти вашего компьютера. У меня она такова, что сразу за массивом "c" идёт массив "f". Выход за границы массива "c" (с [ic], где ic> 46) автоматом означает изменение массива f.
А у вас не сразу. Может, они по разным местам компьютера разбросаны, эти массивы. Может, ещё что.
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали: