Почему меняется значение переменной? - C (СИ)
Формулировка задачи:
Здравствуйте. Пишу вот такой код:
Смотрю через strace, получаю такую картинку:
Как значение ID перескакивает с 4 до 600? Что то намудрил с указателем, не могу понять, что именно.
Листинг программы
- #include <stdio.h>
- #include <sys/ioctl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <linux/fb.h>
- #include <unistd.h>
- int main (void)
- {
- int *pi = NULL;
- int ID = open("/dev/fb0", O_RDWR|O_NONBLOCK);
- ioctl(ID, FBIOGET_VSCREENINFO, &pi);
- ioctl(ID, FBIOPUT_VSCREENINFO, &pi);
- ioctl(ID, 0x4040462e, 0xbe94eac0);
- ioctl(ID, 0x4004462f, 0xbe94ead8);
- return 0;
- }
Листинг программы
- open("/dev/fb0", O_RDWR|O_NONBLOCK) = 4
- ioctl(4, FBIOGET_VSCREENINFO, 0xbec29d4c) = 0
- ioctl(600, FBIOPUT_VSCREENINFO, 0xbec29d4c) = -1 EBADF (Bad file descriptor)
- ioctl(600, 0x4040462e, 0xbe94eac0) = -1 EBADF (Bad file descriptor)
- ioctl(600, 0x4004462f, 0xbe94ead8) = -1 EBADF (Bad file descriptor)
- open("/dev/tty", O_RDWR|O_NOCTTY|O_NONBLOCK) = 5
- writev(5, [{"*** stack smashing detected ***:"..., 33}, {"./a.out", 7}, {" terminated\n", 12}], 3*** stack smashing detected *) = 29
Решение задачи: «Почему меняется значение переменной?»
textual
Листинг программы
- #include <stdio.h>
- // Read in header files
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <linux/fb.h>
- #include <unistd.h>
- #include <string.h>
- #include <sys/mman.h>
- #include <sys/ioctl.h>
- #define putpixel(_x, _y, _c) \
- if ((_x) & 01) { \
- data[((_y)*width + (_x)) >> 1] &= 0xF0; \
- data[((_y)*width + (_x)) >> 1] |= (_c & 0x0F); \
- } else { \
- data[((_y)*width + (_x)) >> 1] &= 0x0F; \
- data[((_y)*width + (_x)) >> 1] |= ((_c & 0x0F) << 4); \
- }
- int main(int argc, char** argv) {
- int width = 0;
- int height = 0;
- int row, column, i, j;
- // open framebuffer device and read out info
- int fd = open("/dev/fb0", O_RDWR);
- struct fb_var_screeninfo screeninfo;
- ioctl(fd, FBIOGET_VSCREENINFO, &screeninfo);
- // determine size
- width = screeninfo.xres;
- height = screeninfo.yres;
- printf("Size: %d x %d\n", width, height);
- // embed framebuffer into memory
- unsigned char *data = (unsigned char*)
- mmap(0, width * height / 2,
- PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- // Clear memory (4 bpp)
- memset(data, 0, width * height / 2);
- // Draw a box
- for (i = 100; i <= 200; ++i) {
- putpixel(300, i, 0xF);
- putpixel(400, i, 0xF);
- putpixel(i+200, 100, 0xF);
- putpixel(i+200, 200, 0xF);
- }
- // mask framebuffer out of memory
- munmap(data, width * height / 2);
- ioctl(3, 0x4040462e, 0);
- }
Объяснение кода листинга программы
- #include
Включает в себя файл стандартного ввода/вывода, который необходим для работы с функциями вывода в консоль. - #include <sys/types.h> Включает в себя файл типов системных вызовов, который содержит определения типов данных для системных вызовов.
- #include <sys/stat.h> Включает в себя файл статистики системных вызовов, который содержит определения для манипулирования файловой системой.
- #include
Включает в себя файл открытий файлов, который содержит определения для манипулирования файлами. - #include <linux/fb.h> Включает в себя заголовочный файл Linux Frame Buffer, который содержит определения для работы с фреймбуфером.
- #include
Включает в себя файл системных вызовов, который содержит определения для низкоуровневых системных вызовов. - #include
Включает в себя файл строки, который содержит определения для манипулирования строками. - #include <sys/mman.h> Включает в себя файл памяти MAP, который содержит определения для манипулирования памятью MAP.
- #include <sys/ioctl.h> Включает в себя файл управления вводом/выводом, который содержит определения для управления устройствами ввода/вывода.
#define putpixel(_x, _y, _c) \
Это определение макросаputpixel
, который будет использоваться в коде для установки пикселя на экране.if ((_x) & 01) {\
Это условие проверяет, является ли самый старший бит x равным 1.data[((_y)*width + (_x)) >> 1] &= 0xF0;
Этот код обновляет значение указанного адреса в массивеdata
, сбрасывая нижние 4 бита.data[((_y)*width + (_x)) >> 1] |= (_c & 0x0F);
Этот код обновляет значение указанного адреса в массивеdata
, устанавливая нижние 4 бита равными значению цвета.else {\
Это условие проверяет, является ли самый старший бит x равным 0.data[((_y)*width + (_x)) >> 1] &= 0x0F;
Этот код обновляет значение указанного адреса в массивеdata
, устанавливая только нижние 4 бита.data[((_y)*width + (_x)) >> 1] |= ((_c & 0x0F) << 4);
Этот код обновляет значение указанного адреса в массивеdata
, устанавливая верхние 4 бита равными значению цвета.int main(int argc, char** argv) {\
Это определение функцииmain
, которая является точкой входа в программу.int width = 0;
Эта переменная инициализирует ширину экрана.int height = 0;
Эта переменная инициализирует высоту экрана.int row, column, i, j;
Эти переменные используются для итерации по экрану при рисовании прямоугольника.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д