1

Тема: Вивід адреси

Взявся на свою голову вчити сі. Все наче виходить, але не дається мені одна цікава задача поки що. Є завдання вивести адресу змінної, зміст в шіснадцядковому вигляді і просто зміст функцією write. Зміст в шіснадцятковому вигляді і просто зміст можу вивести без проблем а от саму адресу не виходить. Я так розумію що треба записати значення адреси в змінну unsigned long int алеж стикаюсь з тим що значення виходить за рамки цього типу. От власне хотів би почути пораду або приклад як це можна зрозуміть та виконать

2

Re: Вивід адреси

Цілий тип, у який гарантовано влазить адреса, зветься size_t (визначено у <stddef.h>, але використовується в інших бібліотеках також). Використовується для визначення розміру об'єктів у пам'яті. Специфікатор розміру для форматованого виводу size_t - z (%zu чи %zx).
size_t беззнаковий, але має знаковий аналог - ptrdiff_t, який використовується, як можна здогадатися, для обчислення різниці між адресами.

Подякували: leofun01, Potaskun2

3

Re: Вивід адреси

Перепрошую, зачитався вашим рішенням і не написав правильного.
Для виведення покажчиків є окремий специфікатор - %p. Не треба нікуди його перетворювати.

Подякували: leofun01, Potaskun2

4

Re: Вивід адреси

Секрет полягає в тому що мені потрібно написати функцію тільки використовуючи функцію write і не використовуючі інші бібліотеки хоча може і помиляюсь... А без використання типу size_t Це можливо зробити?

5

Re: Вивід адреси

А без використання типу size_t Це можливо зробити?

Звісно. Ідея size_t в тому, що розмір покажчика залежить від архітектури; на 32-бітних системах це 4 байти, на 64-бітних - 8 байтів. Вам, швидше за все, потрібен unsigned long long int, і саме так для вашої архітектури size_t і визначений.

Подякували: Potaskun1

6

Re: Вивід адреси

koala написав:

Цілий тип, у який гарантовано влазить адреса, зветься size_t (визначено у <stddef.h>, але використовується в інших бібліотеках також). Використовується для визначення розміру об'єктів у пам'яті. Специфікатор розміру для форматованого виводу size_t - z (%zu чи %zx).
size_t беззнаковий, але має знаковий аналог - ptrdiff_t, який використовується, як можна здогадатися, для обчислення різниці між адресами.

Цілі типи, у які гарантовано влазить адреса, звуться uintptr_t/intptr_t.
А в size_t гарантовано влазить розмір об'єкта (значення саме цього типу повертає sizeof()).
Про те, що це різні речі, може розповісти compact модель пам'яті для i80x86 у 16-бітному режимі ядра, коли розмір об'єкта не може бути більшим за (64К-1) і для size_t досить 16 біт, а вказівники 32-бітні (seg:offs) і для void* та відповідно uintptr_t треба 32 біти.
Подібна штука може бути для 80386+ у 32-бітному режимі (сегментація працює) при не пласкій моделі, і size_t 32-бітний але адреса потребує пари 32-бітних значень seg:offs

p.s. А ще є ssize_t, для якого гарантовано що він може зберігати щонайменше одне від'ємне число — -1

Подякували: leofun01, koala, Potaskun3

7

Re: Вивід адреси

void print_addr(unsigned long long int addr, int i){
    char a[] = "0123456789abcdef";

    if(addr > 16){
        print_addr(addr / 16, i + 1);
    }

    if(addr < 16){
        while(i != 15){
            putchar('0');
            i++;
        }
    }

    putchar(a[addr % 16]);
}

Ось так вийшло
Алеж то тільки початок программи

8

Re: Вивід адреси

Використовуйте тег code

Якщо функція повинна друкувати значення вказівника, то краще щоб її аргумент мав тип void*, а всі приведення до цілих чисел робилися всередині.
Тобто краще зробити щось таке

/* може знадобитися ще десь */
void print_hex(unsigned long long value)
{
    /* ... */
}

void print_addr(void *addr)
{
    print_hex((unsigned long long int)addr);
}

Рекурсія тут не надто потрібна штука, і якщо без неї можна обійтися — краще обійтися.
Можна друкувати у локальний масив, який спочатку заповнювати ззаду починаючи з останньої цифри, а тоді його вивести через write().
І зваовнювати тоді можна без ділення

    /* Тіло циклу, індекс i біжить від максимального значення до 0
       Початкові нулі вийдуть автоматично
    */
    str[i] = "0123456789abcdef"[value & 0x0F];
    value >>= 4;