Необычные способы применения указателей в C-C++

в 22:30, , рубрики: C, c++, указатели

Всем привет. Указатели люди воспринимают по-разному и многие их, мягко говоря, не очень любят. Ну, если они выглядят так:

float(*(*mymegapointer)(double(*)(int)))(int)

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

Начало массива

Имя массива — это указатель на его первый элемент. То есть, если функция f() принимает в качестве аргумента массив, то она принимает на самом деле указатель на его 1-ый элемент. Таким образом, можно схитрить относительно начала массива:

char a[6] = "hello";
puts(a + 1);

Этот фрагмент программы выведет на экран «ello», то есть, выведет слово со второго символа. Так можно выводить на экран строку с n-ого символа вот так:

puts(str + (n - 1));

Конечно, это не единственное применение этой «хитрости», но идею, я надеюсь, вы поняли.

Шифрование текста

Пусть у нас int занимает 4 байта, а char — 1 байт. Тогда в переменной типа int может поместиться строка из 4-х символов. После этого нам остаётся эту строку прочитать как int — и всё! Строка из 4-х символов зашифрована. То есть, длинную строку можно разбить на кусочки, зашифровать каждый из них и получить набор на первый взгляд ничего не значащих чисел.

#include <stdio.h>

int main(int argc, char* argv[]) {
  int i;
  char* str = (char*)&i;
  scanf("%s", str);
  printf("%in", i);
  scanf("%i", &i);
  printf("%sn", str);
  return 0;
}

Эта программка просит пользователя ввести строку (не более 4-х символов длиной) и выводит на экран число. Потом просит ввести число и выводит по нему строку. Шифрование можно усовершенствовать, к примеру, умножая или деля полученные числа на 2, 3 и т.д. Ну, это уже на ваше усмотрение.

Доступ к защищённым полям класса

На что указывает указатель на объект класса? Логично, на объект. Объект — это выделенная память, в которой располагаются поля класса одно за другим. Указатель на объект на самом деле указывает на первое поле в классе. И неважно, public оно или private. Так что можно просто привести указатель на объект к типу этого самого поля и разыменовать его. А чтобы получить доступ к следующему полю класса, нужно прибавить к указателю на первое поле единичку.

Код:

#include <iostream>

class test {
public:
  test();
  void showvali();
  void showvalf();

private:
  int vali_;
  float valf_;
};

test::test() {
  vali_ = 0;
  valf_ = 0.0;
}

void test::showvali() {
  std::cout << vali_ << "n";
}

void test::showvalf() {
  std::cout << valf_ << "n";
}

int main(int argc, char* argv[]) {
  test* t = new test;
  int* vali = (int*)t;
  float* valf = (float*)(vali + 1);
  *vali = 5;
  *valf = 10.84353;
  t->showvali();
  t->showvalf();
  delete t;
  return 0;
}

Вот, пара приколов, которые можно делать с указателями. Они, конечно, не единственные, но хотя бы несколько. Всем пока!

Автор: username666

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js