(02.04.2012 22:04)Efrit Wrote: [ -> ]Это не "тонкости", это вообще должно быть на уровне гигиены
Как "помыть руки перед едой". Если переменная содержит размер чего-либо (неважно чего), или же переменная является индексом массива - то её обязательно нужно объявлять как unsigned.
я считаю, что это хоть и правильный способ, но слишком муторный. в С++ он оправдан, но в языках с более строгим приведением типов может доставлять неудобства в надобности явно приводить переменную к беззнаковому типу (к тому же, большинство таких языков отслеживают выход за рамки массива).
(02.04.2012 22:04)Efrit Wrote: [ -> ]Создавать объекты в куче без особой надобности плохо, потому что это часто приводит к утечкам памяти.
только если потом эти массивы куда-нибудь переприсваивать, возвращать в результате функции и т.п. "открывающая скобка" new и "закрывающая скобка" delete для меня как для тебя индексы и размеры беззнаковых типов.
(02.04.2012 22:04)Efrit Wrote: [ -> ]Например, после такой инициализации нельзя делать return - будет явная утечка памяти, равно как и при break с continue.
почти всегда алгоритм можно построить таким образом, что он будет иметь ровно одну точку входа и одну точку выхода.
Вирт в Оберонах вообще убрал беззнаковый тип. Для 32 бит хватает и двухгигового размера, а для 64 знаковый тип неисчерпаем.
Quote:почти всегда алгоритм можно построить таким образом, что он будет иметь ровно одну точку входа и одну точку выхода.
Всегда.
если использовать goto - да, всегда. хотя контрпример привести не могу.
Дейкстра доказал, что любая программа может быть переписана без goto. Break/continue/return/raise - это goto разной степени ограниченности. У меня любой исходник без указанных. Размеры - до 15 килострок (Эра и WiseEval).
gamecreator Wrote:почти всегда алгоритм можно построить таким образом, что он будет иметь ровно одну точку входа и одну точку выхода.
Да, я знаю.
Согласись ведь, что такой код:
PHP Code:
char* name_of_digit(unsigned int* digit) // функция возвращает название цифры в десятичной системе
{
if (!digit) return "Error: null pointer";
switch (*digit)
{
case 0: return "Zero";
case 1: return "One";
case 2: return "Two";
case 3: return "Three";
case 4: return "Four";
case 5: return "Five";
case 6: return "Six";
case 7: return "Seven";
case 8: return "Eight";
case 9: return "Nine";
default: return "Error: non-digit";
}
}
выглядит значительно лучше, чем если бы он составлялся без goto-подобных
switch и
return?
Berserker Wrote:Вирт в Оберонах вообще убрал беззнаковый тип.
Ну и зря. Например, я хочу написать свой класс - динамический массив типа наподобие
std::vector, с перегруженной операцией "квадратные скобки". И при этом, я хочу иметь нумерацию его элементов именно с нуля - дабы программист не мог обратиться к "отрицательному" элементу. И как же мне сделать это в Обероне, если там нету беззнакового типа?
(03.04.2012 10:55)Efrit Wrote: [ -> ]Согласись ведь, что такой код выглядит значительно лучше, чем если бы он составлялся без goto-подобных switch и return?
ай-яй-яй! как ты мог забыть про статический массив? он тут как нельзя кстати (и зачем вообще указатель передавать, это ведь не позволит передавать в функцию обычные значения; и почему это вдруг цифра (у тебя!!!) потребовала 32 бита?):
PHP Code:
char* name_of_digit(unsigned char digit) // функция возвращает название цифры в десятичной системе
{
static char names[10][] = {"Zero","One","Two","Three","Four","Five","Six","Seven","Eight","Nine"};
if (digit >=0 && digit <=9) return names[digit];
else return 0;
}
(03.04.2012 10:55)Efrit Wrote: [ -> ]И как же мне сделать это в Обероне, если там нету беззнакового типа?
одна проверка, одно исключение
gamecreator Wrote:ай-яй-яй! как ты мог забыть про статический массив? он тут как нельзя кстати (и зачем вообще указатель передавать, это ведь не позволит передавать в функцию обычные значения; и почему это вдруг цифра (у тебя!!!) потребовала 32 бита?)
А причём здесь всё это? Как захотел объявить функцию, так и объявил. Понятное дело, что в реальности я всегда передаю обычные числа по значению... Ты смотри не на сигнатуру функции, а внутрь неё.
А приведённый тобой код содержит
return
gamecreator Wrote:одна проверка, одно исключение
Да я это прекрасно понимаю. Только в таком случае, ошибка будет обнаружена лишь на этапе исполнения программы. В то время как при использовании
unsigned - уже на этапе компиляции!
(03.04.2012 16:05)Efrit Wrote: [ -> ]А приведённый тобой код содержит return 
ой. но это легко решаемо (тем более, что оказывается в многомерных массивах символов таки нужно указывать все размеры

хотя это логично, учитывая что в памяти они будут одномерными; более того, функция должна возвращать указатель на константу):
PHP Code:
const char* name_of_digit(unsigned char digit) // функция возвращает название цифры в десятичной системе
{
static char names[11][6] = {"Zero","One","Two","Three","Four","Five","Six","Seven","Eight","Nine",0};
if (digit <0 || digit >10) digit=10;
return names[digit];
}
(03.04.2012 16:05)Efrit Wrote: [ -> ]В то время как при использовании unsigned - уже на этапе компиляции!
только если ты напрямую впишешь туда отрицательную константу
кстати в таком случае при ошибке возвратится не нулевой указатель, а пустая строка.
для возвращения нулевого указателя придется объявить переменную:
PHP Code:
const char* name_of_digit(unsigned char digit) // функция возвращает название цифры в десятичной системе
{
static char names[10][6] = {"Zero","One","Two","Three","Four","Five","Six","Seven","Eight","Nine"};
char *result = 0;
if (digit >=0 && digit <=9) result = names[digit];
return result;
}
Ну и чем твой получившийся код лучше моего?

Тебе приводится вводить не только дополнительную переменную, но и целый двумерный массив
(кстати, нафига он static?) - и всё лишь ради того, чтобы избежать дублирования
return-ов. Мне же проще использовать
shared_ptr - и создавать ВСЁ в стеке, не парясь про утечки памяти при
return-ах.
gamecreator Wrote:только если ты напрямую впишешь туда отрицательную константу
Да хотя бы и так. Всё равно, я получу сообщение об ошибке уже на этапе компиляции, и гарантированно исправлю её - в то время как ты узнаешь об ошибке лишь тогда, когда пользователь доберётся до критичной строчки кода. А это может случиться через сто лет, если код большой и всевозможных ситуаций много. Есть разница?
К тому же - сейчас, даже если вписать на место
unsigned-переменной просто
int-переменную
(не обязательно константу) - то нормальные компиляторы всегда выдадут варнинг. То есть ошибка в любом случае будет замечена...
Ну вот я кажется уже неплохо стал ориентироваться в ссылках и указателях (за что всем спасибо)
Но все же вопросы остались.
Состряпал код, который внезапно работал только на половину.
Входной массив 012345, выходной 123455.
В функции прибавляю к каждому значению ячейки 1 (как видите последний не захотел)
PHP Code:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int kakoy_to_massiv[5];
for (int i=0; i<6; i++){
kakoy_to_massiv[i]=i;
Label2->Caption=Label2->Caption+kakoy_to_massiv[i];
}
kakaya_to_functcia(&kakoy_to_massiv[0], &kakoy_to_massiv[5]);
for (int i=0; i<6; i++){
Label1->Caption=Label1->Caption+kakoy_to_massiv[i];
}
}
//----------------
void kakaya_to_functcia(int *a, int *g){
for (int i=0; i<6; i++){
*(a+i)+=1; // Увеличиваю значение на 1
//a[i]+=1; //Второй вариант увеличения
}
//*g=7; //Попытка изменить 5-ый элемент вручную (безуспешно)
}
//---------------------------------------------------------------------------
После долгих попыток заставить работать последний адрес массива я решил попробовать вывести этот самый злосчастный адрес на форму, и посмотреть на него (может прозрение случилось бы,не сидеть же сложа руки =) ).
Корректно вывести не получилось(как мне кажется он неверен.) (Кстати не подскажите как?)
Но код
внезапно заработал!
Почему?
PHP Code:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int kakoy_to_massiv[5];
for (int i=0; i<6; i++){
kakoy_to_massiv[i]=i;
Label2->Caption=Label2->Caption+kakoy_to_massiv[i];
}
kakaya_to_functcia(&kakoy_to_massiv[0], &kakoy_to_massiv[5]);
for (int i=0; i<6; i++){
Label1->Caption=Label1->Caption+kakoy_to_massiv[i];
}
//ВОТ ЭТОТ КУСОК////////////////
int prosto1=55; //
int *prosto2=&prosto1; //
AnsiString adres; //
adres = IntToHex(*prosto2, 8); //
Label3->Caption=adres; //
/////////////////////////////////////
}
//----------------
void kakaya_to_functcia(int *a, int *g){
for (int i=0; i<6; i++){
*(a+i)+=1;
//a[i]+=1;
}
//*g=7;
}
P.S. В книге "Моя первая программа на C/C++ - Нейбауэр А. " хорошо написано, а вот в справочнике "Программирование в C++ Builder А. Я. Архангельский" я недостаточно понял =(
Пакка, ещё бы твой пример работал

У тебя массив
kakoy_to_massiv состоит лишь из 5 элементов, в то время как ты пытаешься "пройтись" вплоть до шестого его элемента
(индексы от 0 до 5 включительно, то бишь всего 6 штук).
Да и объявлена функция
kakaya_to_functcia как-то коряво. По уму, она должна принимать два элемента: первый - это адрес первого элемента массива, а второй - это размерность этого массива
(в данном случае - число 5). В подобных функциях размерность массива должна
всегда быть одним из её параметров, учти это.
Кстати, скажу тебе по секрету: запись
&kakoy_to_massiv[0] эквивалентна записи
kakoy_to_massiv 
Поскольку "имя массива" в С - это и есть адрес его первого элемента.
Вот тебе
отличная статья про массивы и указатели.
P.S. А вообще здорово, что ты пытаешься разобраться с указателями. Это, возможно, самый сложный шаг в освоении C++.
Quote:выглядит значительно лучше, чем если бы он составлялся без goto-подобных switch и return?
char* result = "error";
switch ...
case ... result = ...
case ... result = ...
return result.
В Обероне массивы начинаются с нуля, отрицательные константные смещения запрещены, границы проверяются во время выполнения.
Berserker Wrote:char* result = "error";
switch ...
case ... result = ...
case ... result = ...
return result.
Ну так
switch-то ты в итоге никуда и не дел
Berserker Wrote:В Обероне массивы начинаются с нуля, отрицательные константные смещения запрещены, границы проверяются во время выполнения.
Так я же говорил про свой класс "массива", а не про "встроенные" обероновские массивы... В C++ я увижу подобную ошибку уже при компиляции, а в Обероне - лишь при исполнении.