LINUX.ORG.RU

Получить адрес двух структур и временно их поменять местами.

 


0

1

Есть некий код:

struct {
...
  unsigned int len;
} type_struct;
type_struct var1, var2;
void func(type_struct &var1F, type_struct &var2F) {
  if var1F.len > var2F.len {
  //тут я хочу поменять указатели на структуры местами, через xor, для дальнейшей работы над ними, но что бы при выходе из функции, адреса var1 и var2 указывали на те же структуры, что и до вызова.
  }
  ...
  return;
}
void main() {
  ...
  func(var1, var2);
  ...
}
И да, код для микроконтроллера, по этому выделение лишних переменных необходимо избежать.


А зачем вообще физически временно менять указатели местами? Почему не поправить код, что бы он использовал то что нужно.

four_str_sam
()

но что бы при выходе из функции, адреса var1 и var2 указывали на те же структуры, что и до вызова.

ты меняешь значения локальных переменных

И да, код для микроконтроллера

Шел бы ты «Язык Си для чайников» почитал.

anonymous
()
Ответ на: комментарий от anonymous

у него похоже это вообще не Си

anonymous
()
struct {
	...
	unsigned int len;
} my_t;

void f(struct my_t *v1, struct my_t *v2) {
	struct my_t *t = v1;
	if (!v1 || !v2) return;
	if (v1->len > v2->len) {
		v1=v2; v2=t;
	}
	...
	return;
}
bormant ★★★★★
()

//тут я хочу поменять указатели на структуры местами, через xor,

не кононичноТМ меняй через -+

a=-(a+b)
b=-(a+b)
a=-(a+b)
qulinxao ★★☆
()
Ответ на: комментарий от four_str_sam

Так как это микроконтролер, мне нужно уменьшить код до минимума, не использовать лишние переменные.

struct {
  byte data[128] = {0};
  unsigned int len;
} type_struct;
Нужно структуру, у которой байты заполнены меньше (len), заполнить до такой же длины второй структуры, по определённому алгоритму, посчитанной на основании данных более длинной структуры. Сейчас перед каждым вызовом функции func, сравнивается какая структура более длинная, она передаётся вторым параметром, менее короткая первым параметром. Но таких вызовов очень много в различных местах, а каждое дополнительное сравнение перед вызовом функции это дополнительные байтики во флэше выделенного для кода в контроллере, и мне, эти байтики, нужно выкроить. Поэтому хочу сравнить уже внутри функции, убрав сравнение до вызова функции.

Viper
() автор топика

С xor-ом не забыть проверить указатели на равенство:

struct {
	...
	unsigned int len;
} my_t;

void f(struct my_t *v1, struct my_t *v2) {
	if (!v1 || !v2 || v1==v2) return;
	if (v1->len > v2->len) {
		v1^=v2; v2^=v1; v1^=v2;
	}
	...
	return;
}

bormant ★★★★★
()

У тебя видать c++ ссылки, а не указатели. У тебя не получится сделать то, что ты хочешь.

anonymous
()
Ответ на: комментарий от bormant

Тогда мне нужно будет править вызов функции, будет не func(var1,var2), а func(&var1, &var2). Не хотелось бы, да и доп указатель используется, хотя это чисто по Сишному, ИМХО. У меня получилось, что-то похожее на такое, имеет ли право на существование такой код:

void func(type_struct &var1F, type_struct &var2F) {
  if (var1F.len > var2F.len) {
    (int&)var1F = int(&var1F) ^ int(&var2F);
    (int&)var2F = int(&var2F) ^ int(&var1F);
    (int&)var1F = int(&var1F) ^ int(&var2F);
  }
  ...
  return;
}
После выхода из функции func(var1,var2) var1 и var2 указывает на туже лбласть памяти, что и до входа в функцию?

Viper
() автор топика
Последнее исправление: Viper (всего исправлений: 1)
Ответ на: комментарий от bormant

А вот это, для меня, более понятно. Спасибо. А мой вариант будет работать так же? Хочу сравнить два варианта и тот который использует меньше байт флэша, заюзать.

Viper
() автор топика

У тебя ж ссылки, а не указатели. Вы либо крестик снимите, либо трусы оденьте.

joy4eg ★★★★★
()
Ответ на: комментарий от Viper

Кастовать адрес в int в общем случае плохая идея, попытка перенести код на другую платформу, где sizeof(int)!=sizeof(int&), может обернуться пляской на детских граблях...

bormant ★★★★★
()
Ответ на: комментарий от Viper

Так как это микроконтролер, мне нужно уменьшить код до минимума, не использовать лишние переменные

Сейчас я вас научу плохому.

Микроконтроллеры уже лет пять-десять назад достигли того уровня, когда нет нужды трястись за каждый байтик.

А если вашей задаче нужно действительно много памяти - так многие уже давно умеют использовать внешнюю DDR память.

Вы уверены что вам такие оптимизации нужны? Просто пока вы близко не «подойдете» к потолку производительности контроллера, нет смысла оптимизироваться - это слишком «долго», иногда дешевле все-таки купить более «крутой» микроконтроллер, чем тратить время на оптимизации.

RiseOfDeath ★★★★
()
Последнее исправление: RiseOfDeath (всего исправлений: 3)
Ответ на: комментарий от Viper

Так как это микроконтролер, мне нужно уменьшить код до минимума, не использовать лишние переменные.

читать ABI для конкретного МК. в 99.99% случаев аргументы функции сидят в двух регистрах - как обменять значения на регистрах см.соотв мануал :-)

и да, такая оптимизация ЗЛО

MKuznetsov ★★★★★
()
Ответ на: комментарий от RiseOfDeath

Я не создаю железку с нуля, мне необходимо сделать некоторые доработки этой железки, точнее её кода. Вот и не хватает 32Kb ISP flash для добавления кода на atmega328. Вот и занимаюсь выкраиванием необходимых байтов. А так как я не программист, а учился программировать на первых курсах универа и то, не на С++, и в школьные времена, на спектруме, как хобби, вот и возникают, возможно, глупые вопросы.

Viper
() автор топика
Последнее исправление: Viper (всего исправлений: 1)

if var1F.len > var2F.len
C

type_struct &var2F
C

ндя

next_time ★★★★★
()
Ответ на: комментарий от RiseOfDeath

Микроконтроллеры уже лет пять-десять назад достигли того уровня, когда нет нужды трястись за каждый байтик.

это не так — полно МК с 256 байтами неконстантной памяти

next_time ★★★★★
()
Ответ на: комментарий от Viper

Тогда мне нужно будет править вызов функции, будет не func(var1,var2), а func(&var1, &var2).

Э... Если у вас достаточно умный C++ный компилятор, то

void func_impl(type_struct * v1, type_struct * v2) {
...
}
inline void func(type_struct & v1, type_struct & v2) {
  func_impl(&v1, &v2);
}
И у вас в коде все вызовы func(var1,var2) автоматически будут приводить к func_impl(&var1,&var2). Причем без затрат в run-time.

Ну а обменять значения v1 и v2 местами внутри func_impl вы можете через asm и работу с регистрами вашей железяки. Если уж вам места на стеке жалко.

Хотя, если компилятор таки продвинутый и содержит std::swap, то можно вызвать std::swap в начале func_impl. Или написать свой вариант swap-а.

Кстати говоря, размеры len определяются в run-time или они известны уже в compile-time?

eao197 ★★★★★
()

Всем спасибо. len в структуре меняется в run-time. Предложенный вариант с рекурсивным вызовом функции, по мне, лучший. А то, что я там напридумывал, не понятно как работает. Да и почитал я о ссылках и указателях, понял, что с сылками мной задуманное и не должно было получиться, так как после инициализации адрес на который ссылается сылка уже изменить нельзя.

Viper
() автор топика
Последнее исправление: Viper (всего исправлений: 1)

Не сделав var1 и var2 указателями ты ничего не сделаешь. Если это глобальные переменные, при использовании var1/var2 в машинный код забивается статическое смещение, если переменные на стеке - смещение относительно фрейма. Никаких адресов которые ты мог бы поменять там нет.

slovazap ★★★★★
()

Так как это микроконтролер, мне нужно уменьшить код до минимума, не использовать лишние переменные.

Вот и не хватает 32Kb ISP flash для добавления кода на atmega328. Вот и занимаюсь выкраиванием необходимых байтов.

Дело в том, что инструкции и локальные переменные - это две разные вещи. Только инструкции и глобальные переменные едят flash. Поэтому нужно как раз упрощать код, а не усложнять, при необходимости выделяя дополнительные локальные переменные.

Ещё есть параметры оптимизации с дилеммой: скорость (-O3) против размера (-Os). Для скорости компилятор будет пытаться «подставить» как можно больше кода, избавившись от вызова функции, а при оптимизации для размера - нет. Так что проверь опции. А то твою ручную оптимизацию в «не ту сторону» компилятор всё равно выпрямит. Ещё, есть и компиляция для отладки (-g), которая занимает ещё больше флеша.

gag ★★★★★
()
Ответ на: комментарий от gag

Переменные лишние я не хочу использовать, так как мне не известно, сколько из 2Kb под них используется в процессе работы, можно посчитать, сколько для глобальных выделяется, там тоже почти под завязку, но есть ещё множетсво переменных в функциях, которые вызываются из других функций со своими переменными, память под которые то выделяется, то освобождается. В итоге код дописываю и стараюсь не выделять переменные, так как контролер, при не хватке 2Kb об этом не напишет, а будет глючить, в какие-то моменты, а определить причину глюка будет тяжело. Сейчас занимаюсь оптимизацией длины кода, для добавления своего, вместо множества if перед func, я делаю один if в func, размер кода это уменьшило так как я и рассчитывал, учитывая, что вызывов func десятки, по всему коду.

Viper
() автор топика
Ответ на: комментарий от slovazap

Ну не обязательно адреса поменять, можно бы было и смещение у двух ссылок поменять, но, как я понял, этого не задумывалось для них.

Viper
() автор топика
Ответ на: комментарий от Viper

А, в функции-то. Интересно что бы вы поменяли если бы она заинлайнилась. В любом случае это UB.

slovazap ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.