Форум программистов
 
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

Вернуться   Форум программистов > Технологии > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail


Ответ
 
Опции темы
Старый 19.08.2015, 10:29   #61
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,840
По умолчанию

Цитата:
А другой код - чей?
А чей угодно. Вообще сторонний, из другой ДЛЛ например. Или из другого юнита. Не важно. Сам смысл - дать возможность выполнить любую функцию из другой функции, передав на нее указатель. Причем выполняющая сторона может не ведать что выполняет.
Цитата:
А что если в аргументах код той же функции?
Значит рекурсия может получиться )
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 19.08.2015, 14:47   #62
Rififi
Старожил
 
Регистрация: 19.08.2009
Сообщений: 2,120
По умолчанию

Smitt&Wesson

Если мы передадим в вызываемую функцию просто созданный массив, то внутри вызываемой функции мы получим только его копию.
...
Мы получим ссылку на уже созданный массив и функция будет обрабатывать именно его. Как мы видим, функция ничего не возвратила в явном виде. Но это не так. Исходный массив был изменён и возвращён функцией через её параметры.

смешались в кучу люди, кони... :D

по пунктам:

в какой-то функции был создан пустой локальный массив:
int N = 100;
int * array = new int[N];


это не массив, а указатель на целое.

Если мы передадим в вызываемую функцию просто созданный массив, то внутри вызываемой функции мы получим только его копию.

если это настоящий с++, а не паленая китайская копия низкого качества, то передать копию массива в качестве аргумента нельзя. от слова совсем. такие дела.

Мы получим ссылку на уже созданный массив

никакой ссылки вы не получите. будет передана копия указателя.

Исходный массив был изменён и возвращён функцией через её параметры.

функция ничего не возвращает через параметры. в таком варианте функция может модифицировать область адрес начала которой сохранен в переданном указателе.
Rififi вне форума Ответить с цитированием
Старый 27.08.2015, 04:51   #63
Алексей_2012
t45t
Участник клуба
 
Аватар для Алексей_2012
 
Регистрация: 20.03.2012
Сообщений: 1,777
По умолчанию

С примером Смита разобрался, и тут же вопрос:

Что если в аргументах только указатель на массив, а его размер-неизвестен, то применение цикла for будет нерелевантно, а вот цикл с предусловием- в самый раз. Как, например , получить сумму элементов массива, не зная его размера?

Почему именно просуммировать - потому что еще не умею возвращать массивы. Поэтому пока акцент на void-функцию. Была идея вернуть указатель на массив структур, но как потом с этим всем работать-не знаю, в гугле глухо.

И второй вопрос.

Что значит:

Вернуть ссылку из функции.
Вернуть ссылку из указателя на функцию (надеюсь так сказал, пример в первом посте)

Зачем вообще возвращать ссылки?

Зачем в аргументах функции ссылки тогда, когда можно взять указатель?


Да, я читал о ссылках, хороших примеров не нашел кроме

int x;
int *p=&x;

Оттуда и вопрос.

А в лабораторных мы ссылки нигде, кроме как в scanf("%d",&...)не использовали, поэтому оттуда и непонятки.
from dark to light)

Последний раз редактировалось Вадим Мошев; 30.08.2017 в 21:32.
Алексей_2012 вне форума Ответить с цитированием
Старый 27.08.2015, 06:05   #64
challengerr
Участник клуба
 
Аватар для challengerr
 
Регистрация: 30.07.2008
Сообщений: 1,596
По умолчанию

У центрального процессора есть регистры. В регистре могут храниться какие-то данные или адрес на данные в памяти. Указатель - это регистр процессора, в котором находится адрес данных. Указатели - это низкоуровневый механизм доступа к данным.

>>МойКласс new_obj;
>>МойКласс *new_obj;

В первом случае создается экземпляр класса.
Во втором случае экземпляр класса не создается. Обращение по такому указателю может быть ошибкой, так как сперва требуется динамически выделить память под класс.

>>3) *token = expr[i]; - эта строчка тоже не ясна, ведь объявили переменную не как указательную

Имя массива в С является указателем.

& является унарным оператором получения адреса операнда в выражении. То есть &i получает адрес хранения переменной i в памяти. Описание унарного оператора & находится в части 6.5.3.2 международного стандарта языка С по ISO (Международная организация по стандартизации). результат выполнения оператора & - указатель на тип.

Память процесса является виртуальной. Есть виртуальное адресное пространство процесса (virtual address space) https://msdn.microsoft.com/ru-ru/lib...(v=vs.85).aspx который не представляет действительно физическое размещение объекта в оперативной памяти. Система создает страничную таблицу для каждого процесса, которая используется для трансляции виртуальных адресов в физические. Размер виртуального адресного пространства для процесса - 4 гигабайта. Оно разделено на две партиции: одну для использования процессом и другую для использования системой

>>1) Функция объявлена как указатель-для чего?

Объявление результата, возвращаемого функцией - произвол программиста. Программист выбирает, в каком виде функция должна возвратить значение.

Код:
возвращаемое_значение название_функции(список_аргументов)
{
тело_функции
}
Переменные в функции имеют локальное время существования, если не объявлены как статические (static). В функции переменная i объявлена как статическая, что значит, что она существует все время выполнения программы и инициализируется один раз (раздел 6.2.4 стандарта). это позволило в примере возвратить адрес переменной из функции.


>>Зачем вообще возвращать ссылки?

Описание ссылок в разделе 8.3.2 стандарта языка C++ ISO 2011 года.
Ссылка возвращается для изменения некоторых данных.

В стандарте приведен пример:
Код:
int v[20];
// ...
int& g(int i) { return v[i]; }
// ...
g(3) = 7;
в котором при возврате ссылки из функции, изменяются данные в массиве v. ( declares the function g() to return a reference to an integer so g(3)=7 will assign 7 to the fourth element of the array v. )

Ссылка это адрес данных. На низком уровне (ассемблер) это выглядит так
Код:
// ebx = &w
lea ebx, w
Инструкция lea ассемблера загружает адрес в регистр процессора. & указывает компилятору, что нужно использовать lea, а не mov при преобразовании в машинные кода программы.

В С++ есть механизм перегрузки операторов (overloaded operators), в нем могут использоваться ссылки.

В стандарте дан пример:
Код:
struct X {
X& operator++(); // prefix ++a
X operator++(int); // postfix a++
};
struct Y { };
Y& operator++(Y&); // prefix ++b
Y operator++(Y&, int); // postfix b++
void f(X a, Y b) {
++a; // a.operator++();
a++; // a.operator++(0);
++b; // operator++(b);
b++; // operator++(b, 0);
a.operator++(); // explicit call: like ++a;
a.operator++(0); // explicit call: like a++;
operator++(b); // explicit call: like ++b;
operator++(b, 0); // explicit call: like b++;
}
>>Зачем в аргументах функции ссылки тогда, когда можно взять указатель?

При перегрузке операторов в классах, не получится взять указатель. Оператор это как бы функция. Например, класс cout использует перегруженный оператор <<, что позволяет записывать конструкции вида cout << 5 << 3.14 << endl;
"SPACE.THE FINAL FRONTIER.This's a voyage of starship Enterprise. It's 5-year mission to explore strange new worlds,to seek out new life and civilizations,to boldly go where no man has gone before"
challengerr вне форума Ответить с цитированием
Старый 27.08.2015, 06:09   #65
challengerr
Участник клуба
 
Аватар для challengerr
 
Регистрация: 30.07.2008
Сообщений: 1,596
По умолчанию

Пример на встроенном ассемблере для объяснения как операторы, указатели, ссылки, массивы C/C++ реализуются на уровне процессора

Код:
#include <stdio.h>
#include <windows.h>


#pragma comment(lib, "user32.lib")
#pragma comment(lib, "kernel32.lib")
#pragma comment(lib, "gdi32.lib")


struct q
{
int a;
int b;
};


void main()
{
int i;
int **m;
int a;
int res;
int* r;
int* z;
int y;
q w;

w.a = 3;
w.b = 4;

int c1;
int c2;
int c3;

char* s1 = "a1\0";
char* s2 = "a2\0";

z = new int[10];

m = new int*[2];
for (i = 0;i < 3 ;i++)
m[i] = new int[3];

m[0][0] = 1;
m[0][1] = 2;
m[0][2] = 3;

__asm
{

// a = 5
mov eax, 5

cmp eax, 5
jnz ext;


mov ebx, 6
mov ecx, 7
mov edx, 8
mov a, eax

// r = &a
lea ebx, a
mov r, ebx

//


// y = *r
mov ecx, r
mov edx, [ecx]
mov y, edx

// z[0] = 8
mov ecx, z
mov edx, 5
mov [ecx], edx

// z[1] = 7
mov edx, 7
mov dword ptr [ecx+4], edx

// z[2] = 8
mov edx, 8
mov dword ptr [ecx+8], edx

// ebx = &w
lea ebx, w
mov edx, ebx
// c3 = &w
mov c3, edx
// c1 = w.a
mov ecx, [edx]
mov c1, ecx
add edx, 4
mov ecx, [edx]
// c2 = w.b
mov c2, ecx

//
push 0

mov ebx, s1
push ebx

mov ecx, s2
push ecx

push 0

call ds:MessageBoxA


push 0
push s1
push s2
push 0
call ds:MessageBoxA

ext:

}

//MessageBox(0, s1, s2, 0);

res = *r;

printf("%x %x %x %x %d %d %d %d %d %d\n", r, &a, res, y, z[0], z[1], z[2], c1, c2, c3);



}
"SPACE.THE FINAL FRONTIER.This's a voyage of starship Enterprise. It's 5-year mission to explore strange new worlds,to seek out new life and civilizations,to boldly go where no man has gone before"
challengerr вне форума Ответить с цитированием
Старый 27.08.2015, 06:32   #66
Алексей_2012
t45t
Участник клуба
 
Аватар для Алексей_2012
 
Регистрация: 20.03.2012
Сообщений: 1,777
По умолчанию

Спасибо, но все равно не очень понял суть. Зачем ссылка при перегрузке оператора? Чтоб например при перегрузке + ,

Программа видела числа слева и справа?
В интернете искал банальные перегрузки, где действие + изменяется на умножение. Не нашел. Суть понимаю зачем нужна перегрузка.

Есть ли наглядный пример, объясняющий- зачем ссылки при перегрузке?


Извиняюсь за тупняк.
from dark to light)
Алексей_2012 вне форума Ответить с цитированием
Старый 27.08.2015, 07:04   #67
challengerr
Участник клуба
 
Аватар для challengerr
 
Регистрация: 30.07.2008
Сообщений: 1,596
По умолчанию

Цитата:
Сообщение от Алексей_2012 Посмотреть сообщение
Спасибо, но все равно не очень понял суть. Зачем ссылка при перегрузке оператора? Чтоб например при перегрузке + ,

Программа видела числа слева и справа?
В интернете искал банальные перегрузки, где действие + изменяется на умножение. Не нашел. Суть понимаю зачем нужна перегрузка.

Есть ли наглядный пример, объясняющий- зачем ссылки при перегрузке?


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

Пример
Код:
#include <stdio.h>

class a1
{
public:
int p1;

a1() { p1 = 5; }
};

class a2
{
public:
int p2;

void f(a1& ref)
{
printf("%d\n", ref.p1);
ref.p1 = 6; // сохраняется
}

void g(a1 r)
{
printf("%d\n", r.p1);
r.p1 = 7; // не сохраняется
}


};


int g(int)
{
return 0;
}

// из стандарта
void f() 
{
int i;
int& r = i; // r refers to i
r = 1; // the value of i becomes 1
int* p = &r; // p points to i
int& rr = r; // rr refers to what r refers to, that is, to i
int (&rg)(int) = g; // rg refers to the function g
rg(i); // calls function g
int a[3];
int (&ra)[3] = a; // ra refers to the array a
ra[1] = i; // modifies a[1]
}


void main()
{

f();
a1 t;
a2 s;
s.f(t);
s.g(t);
s.f(t);
s.g(t);
s.f(t);
s.g(t);

}
"SPACE.THE FINAL FRONTIER.This's a voyage of starship Enterprise. It's 5-year mission to explore strange new worlds,to seek out new life and civilizations,to boldly go where no man has gone before"
challengerr вне форума Ответить с цитированием
Старый 27.08.2015, 07:30   #68
Алексей_2012
t45t
Участник клуба
 
Аватар для Алексей_2012
 
Регистрация: 20.03.2012
Сообщений: 1,777
По умолчанию

Спасибо большое.

А вот на счет mov и lea, откопал старый асм код...

Вывод и ввод строки символов.

Тут, по вашей логике, если так понял lea передает указатель на первый элемент np1.

Код:
jmp m1000
np1 db 'BBedite 4isla$'
m1000:mov ah, 09h
lea dx, np1
int 21h

Тут тоже, а потом используется косвенная адресация, так что, наверное, я не так все понял, или поведение lea зависит от ah?
Код:
jmp m100
par1 label byte
max1 db 100
rd1 db ?
str1 db 101 dup(?)
m100:mov ah,10
lea dx,par1
int 21h

lea si,str1 
mov ch,0
mov cl,rd1
mov dl,0
m1:
cmp dl,[si]
ja m2
mov dl,[si]
m2:
inc si
loop m1
from dark to light)
Алексей_2012 вне форума Ответить с цитированием
Старый 27.08.2015, 07:54   #69
challengerr
Участник клуба
 
Аватар для challengerr
 
Регистрация: 30.07.2008
Сообщений: 1,596
По умолчанию

lea - load effective address (загрузить эффективный адрес)

Код:
mov ah, 09h
lea dx, np1
int 21h
Изменение регистра ah нужно для прерывания 21h, и с lea не связано. В DOS управление железом с помощью прерываний. Это код под DOS, в современной windows такое в пользовательском режиме уже невозможно.
В lea в 16-битный регистр dx помещается адрес последовательности байтов np1
В ah номер требуемой функции dos от прерывания.

Описание прерываний DOS : http://www.codenet.ru/progr/dos/int_0026.php
Int (wikipedia): https://ru.wikipedia.org/wiki/Int_(%...0%B8%D1%8F_x86)
"SPACE.THE FINAL FRONTIER.This's a voyage of starship Enterprise. It's 5-year mission to explore strange new worlds,to seek out new life and civilizations,to boldly go where no man has gone before"
challengerr вне форума Ответить с цитированием
Старый 27.08.2015, 08:01   #70
Алексей_2012
t45t
Участник клуба
 
Аватар для Алексей_2012
 
Регистрация: 20.03.2012
Сообщений: 1,777
По умолчанию

Да, спасибо большое. Жаль нет функий преобразования строки символов в число.
from dark to light)
Алексей_2012 вне форума Ответить с цитированием
Ответ

Здесь нужно купить рекламу за 20 тыс руб в месяц! ) пишите сюда - alarforum@yandex.ru
Без учёта ботов - 20000 человек в день, 350000 в месяц.

Опции темы


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
указатели salmon172 Паскаль, Turbo Pascal, PascalABC.NET 0 31.05.2011 21:34
указатели Артэс Общие вопросы C/C++ 4 07.09.2010 11:08
Указатели Анютик_sexi Помощь студентам 3 16.06.2010 14:38
Указатели AquaticSoul Общие вопросы C/C++ 5 22.12.2009 16:13
[C] массивы, указатели, двойные указатели. Iggel Общие вопросы C/C++ 5 05.05.2009 12:39